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 DEFUN ("random", Frandom
, Srandom
, 0, 1, 0,
51 "Return a pseudo-random number.\n\
52 On most systems all integers representable in Lisp are equally likely.\n\
53 This is 24 bits' worth.\n\
54 With argument N, return random number in interval [0,N).\n\
55 With argument t, set the random number seed from the current time and pid.")
60 unsigned long denominator
;
61 extern long random ();
66 srandom (getpid () + time (0));
67 if (INTEGERP (limit
) && XINT (limit
) > 0)
69 if (XFASTINT (limit
) >= 0x40000000)
70 /* This case may occur on 64-bit machines. */
71 val
= random () % XFASTINT (limit
);
74 /* Try to take our random number from the higher bits of VAL,
75 not the lower, since (says Gentzel) the low bits of `random'
76 are less random than the higher ones. We do this by using the
77 quotient rather than the remainder. At the high end of the RNG
78 it's possible to get a quotient larger than limit; discarding
79 these values eliminates the bias that would otherwise appear
80 when using a large limit. */
81 denominator
= (unsigned long)0x40000000 / XFASTINT (limit
);
83 val
= (random () & 0x3fffffff) / denominator
;
84 while (val
>= XFASTINT (limit
));
89 return make_number (val
);
92 /* Random data-structure functions */
94 DEFUN ("length", Flength
, Slength
, 1, 1, 0,
95 "Return the length of vector, list or string SEQUENCE.\n\
96 A byte-code function object is also allowed.")
98 register Lisp_Object obj
;
100 register Lisp_Object tail
, val
;
105 XSETFASTINT (val
, XSTRING (obj
)->size
);
106 else if (VECTORP (obj
))
107 XSETFASTINT (val
, XVECTOR (obj
)->size
);
108 else if (COMPILEDP (obj
))
109 XSETFASTINT (val
, XVECTOR (obj
)->size
& PSEUDOVECTOR_SIZE_MASK
);
110 else if (CONSP (obj
))
112 for (i
= 0, tail
= obj
; !NILP (tail
); i
++)
118 XSETFASTINT (val
, i
);
121 XSETFASTINT (val
, 0);
124 obj
= wrong_type_argument (Qsequencep
, obj
);
130 DEFUN ("string-equal", Fstring_equal
, Sstring_equal
, 2, 2, 0,
131 "T if two strings have identical contents.\n\
132 Case is significant, but text properties are ignored.\n\
133 Symbols are also allowed; their print names are used instead.")
135 register Lisp_Object s1
, s2
;
138 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
140 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
141 CHECK_STRING (s1
, 0);
142 CHECK_STRING (s2
, 1);
144 if (XSTRING (s1
)->size
!= XSTRING (s2
)->size
||
145 bcmp (XSTRING (s1
)->data
, XSTRING (s2
)->data
, XSTRING (s1
)->size
))
150 DEFUN ("string-lessp", Fstring_lessp
, Sstring_lessp
, 2, 2, 0,
151 "T if first arg string is less than second in lexicographic order.\n\
152 Case is significant.\n\
153 Symbols are also allowed; their print names are used instead.")
155 register Lisp_Object s1
, s2
;
158 register unsigned char *p1
, *p2
;
162 XSETSTRING (s1
, XSYMBOL (s1
)->name
);
164 XSETSTRING (s2
, XSYMBOL (s2
)->name
);
165 CHECK_STRING (s1
, 0);
166 CHECK_STRING (s2
, 1);
168 p1
= XSTRING (s1
)->data
;
169 p2
= XSTRING (s2
)->data
;
170 end
= XSTRING (s1
)->size
;
171 if (end
> XSTRING (s2
)->size
)
172 end
= XSTRING (s2
)->size
;
174 for (i
= 0; i
< end
; i
++)
177 return p1
[i
] < p2
[i
] ? Qt
: Qnil
;
179 return i
< XSTRING (s2
)->size
? Qt
: Qnil
;
182 static Lisp_Object
concat ();
193 return concat (2, args
, Lisp_String
, 0);
195 return concat (2, &s1
, Lisp_String
, 0);
196 #endif /* NO_ARG_ARRAY */
202 Lisp_Object s1
, s2
, s3
;
209 return concat (3, args
, Lisp_String
, 0);
211 return concat (3, &s1
, Lisp_String
, 0);
212 #endif /* NO_ARG_ARRAY */
215 DEFUN ("append", Fappend
, Sappend
, 0, MANY
, 0,
216 "Concatenate all the arguments and make the result a list.\n\
217 The result is a list whose elements are the elements of all the arguments.\n\
218 Each argument may be a list, vector or string.\n\
219 The last argument is not copied, just used as the tail of the new list.")
224 return concat (nargs
, args
, Lisp_Cons
, 1);
227 DEFUN ("concat", Fconcat
, Sconcat
, 0, MANY
, 0,
228 "Concatenate all the arguments and make the result a string.\n\
229 The result is a string whose elements are the elements of all the arguments.\n\
230 Each argument may be a string, a list of characters (integers),\n\
231 or a vector of characters (integers).")
236 return concat (nargs
, args
, Lisp_String
, 0);
239 DEFUN ("vconcat", Fvconcat
, Svconcat
, 0, MANY
, 0,
240 "Concatenate all the arguments and make the result a vector.\n\
241 The result is a vector whose elements are the elements of all the arguments.\n\
242 Each argument may be a list, vector or string.")
247 return concat (nargs
, args
, Lisp_Vectorlike
, 0);
250 DEFUN ("copy-sequence", Fcopy_sequence
, Scopy_sequence
, 1, 1, 0,
251 "Return a copy of a list, vector or string.\n\
252 The elements of a list or vector are not copied; they are shared\n\
257 if (NILP (arg
)) return arg
;
258 if (!CONSP (arg
) && !VECTORP (arg
) && !STRINGP (arg
))
259 arg
= wrong_type_argument (Qsequencep
, arg
);
260 return concat (1, &arg
, CONSP (arg
) ? Lisp_Cons
: XTYPE (arg
), 0);
264 concat (nargs
, args
, target_type
, last_special
)
267 enum Lisp_Type target_type
;
272 register Lisp_Object tail
;
273 register Lisp_Object
this;
277 Lisp_Object last_tail
;
280 /* In append, the last arg isn't treated like the others */
281 if (last_special
&& nargs
> 0)
284 last_tail
= args
[nargs
];
289 for (argnum
= 0; argnum
< nargs
; argnum
++)
292 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
293 || COMPILEDP (this)))
296 args
[argnum
] = Fnumber_to_string (this);
298 args
[argnum
] = wrong_type_argument (Qsequencep
, this);
302 for (argnum
= 0, leni
= 0; argnum
< nargs
; argnum
++)
305 len
= Flength (this);
306 leni
+= XFASTINT (len
);
309 XSETFASTINT (len
, leni
);
311 if (target_type
== Lisp_Cons
)
312 val
= Fmake_list (len
, Qnil
);
313 else if (target_type
== Lisp_Vectorlike
)
314 val
= Fmake_vector (len
, Qnil
);
316 val
= Fmake_string (len
, len
);
318 /* In append, if all but last arg are nil, return last arg */
319 if (target_type
== Lisp_Cons
&& EQ (val
, Qnil
))
323 tail
= val
, toindex
= -1; /* -1 in toindex is flag we are making a list */
329 for (argnum
= 0; argnum
< nargs
; argnum
++)
333 register int thisindex
= 0;
337 thislen
= Flength (this), thisleni
= XINT (thislen
);
339 if (STRINGP (this) && STRINGP (val
)
340 && ! NULL_INTERVAL_P (XSTRING (this)->intervals
))
342 copy_text_properties (make_number (0), thislen
, this,
343 make_number (toindex
), val
, Qnil
);
348 register Lisp_Object elt
;
350 /* Fetch next element of `this' arg into `elt', or break if
351 `this' is exhausted. */
352 if (NILP (this)) break;
354 elt
= Fcar (this), this = Fcdr (this);
357 if (thisindex
>= thisleni
) break;
359 XSETFASTINT (elt
, XSTRING (this)->data
[thisindex
++]);
361 elt
= XVECTOR (this)->contents
[thisindex
++];
364 /* Store into result */
367 XCONS (tail
)->car
= elt
;
369 tail
= XCONS (tail
)->cdr
;
371 else if (VECTORP (val
))
372 XVECTOR (val
)->contents
[toindex
++] = elt
;
375 while (!INTEGERP (elt
))
376 elt
= wrong_type_argument (Qintegerp
, elt
);
378 #ifdef MASSC_REGISTER_BUG
379 /* Even removing all "register"s doesn't disable this bug!
380 Nothing simpler than this seems to work. */
381 unsigned char *p
= & XSTRING (val
)->data
[toindex
++];
384 XSTRING (val
)->data
[toindex
++] = XINT (elt
);
391 XCONS (prev
)->cdr
= last_tail
;
396 DEFUN ("copy-alist", Fcopy_alist
, Scopy_alist
, 1, 1, 0,
397 "Return a copy of ALIST.\n\
398 This is an alist which represents the same mapping from objects to objects,\n\
399 but does not share the alist structure with ALIST.\n\
400 The objects mapped (cars and cdrs of elements of the alist)\n\
401 are shared, however.\n\
402 Elements of ALIST that are not conses are also shared.")
406 register Lisp_Object tem
;
408 CHECK_LIST (alist
, 0);
411 alist
= concat (1, &alist
, Lisp_Cons
, 0);
412 for (tem
= alist
; CONSP (tem
); tem
= XCONS (tem
)->cdr
)
414 register Lisp_Object car
;
415 car
= XCONS (tem
)->car
;
418 XCONS (tem
)->car
= Fcons (XCONS (car
)->car
, XCONS (car
)->cdr
);
423 DEFUN ("substring", Fsubstring
, Ssubstring
, 2, 3, 0,
424 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
425 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
426 If FROM or TO is negative, it counts from the end.")
429 register Lisp_Object from
, to
;
433 CHECK_STRING (string
, 0);
434 CHECK_NUMBER (from
, 1);
436 to
= Flength (string
);
438 CHECK_NUMBER (to
, 2);
441 XSETINT (from
, XINT (from
) + XSTRING (string
)->size
);
443 XSETINT (to
, XINT (to
) + XSTRING (string
)->size
);
444 if (!(0 <= XINT (from
) && XINT (from
) <= XINT (to
)
445 && XINT (to
) <= XSTRING (string
)->size
))
446 args_out_of_range_3 (string
, from
, to
);
448 res
= make_string (XSTRING (string
)->data
+ XINT (from
),
449 XINT (to
) - XINT (from
));
450 copy_text_properties (from
, to
, string
, make_number (0), res
, Qnil
);
454 DEFUN ("nthcdr", Fnthcdr
, Snthcdr
, 2, 2, 0,
455 "Take cdr N times on LIST, returns the result.")
458 register Lisp_Object list
;
463 for (i
= 0; i
< num
&& !NILP (list
); i
++)
471 DEFUN ("nth", Fnth
, Snth
, 2, 2, 0,
472 "Return the Nth element of LIST.\n\
473 N counts from zero. If LIST is not that long, nil is returned.")
477 return Fcar (Fnthcdr (n
, list
));
480 DEFUN ("elt", Felt
, Selt
, 2, 2, 0,
481 "Return element of SEQUENCE at index N.")
483 register Lisp_Object seq
, n
;
488 if (CONSP (seq
) || NILP (seq
))
489 return Fcar (Fnthcdr (n
, seq
));
490 else if (STRINGP (seq
) || VECTORP (seq
))
491 return Faref (seq
, n
);
493 seq
= wrong_type_argument (Qsequencep
, seq
);
497 DEFUN ("member", Fmember
, Smember
, 2, 2, 0,
498 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
499 The value is actually the tail of LIST whose car is ELT.")
501 register Lisp_Object elt
;
504 register Lisp_Object tail
;
505 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
507 register Lisp_Object tem
;
509 if (! NILP (Fequal (elt
, tem
)))
516 DEFUN ("memq", Fmemq
, Smemq
, 2, 2, 0,
517 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
518 The value is actually the tail of LIST whose car is ELT.")
520 register Lisp_Object elt
;
523 register Lisp_Object tail
;
524 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
526 register Lisp_Object tem
;
528 if (EQ (elt
, tem
)) return tail
;
534 DEFUN ("assq", Fassq
, Sassq
, 2, 2, 0,
535 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
536 The value is actually the element of LIST whose car is KEY.\n\
537 Elements of LIST that are not conses are ignored.")
539 register Lisp_Object key
;
542 register Lisp_Object tail
;
543 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
545 register Lisp_Object elt
, tem
;
547 if (!CONSP (elt
)) continue;
549 if (EQ (key
, tem
)) return elt
;
555 /* Like Fassq but never report an error and do not allow quits.
556 Use only on lists known never to be circular. */
559 assq_no_quit (key
, list
)
560 register Lisp_Object key
;
563 register Lisp_Object tail
;
564 for (tail
= list
; CONSP (tail
); tail
= Fcdr (tail
))
566 register Lisp_Object elt
, tem
;
568 if (!CONSP (elt
)) continue;
570 if (EQ (key
, tem
)) return elt
;
575 DEFUN ("assoc", Fassoc
, Sassoc
, 2, 2, 0,
576 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
577 The value is actually the element of LIST whose car is KEY.")
579 register Lisp_Object key
;
582 register Lisp_Object tail
;
583 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
585 register Lisp_Object elt
, tem
;
587 if (!CONSP (elt
)) continue;
588 tem
= Fequal (Fcar (elt
), key
);
589 if (!NILP (tem
)) return elt
;
595 DEFUN ("rassq", Frassq
, Srassq
, 2, 2, 0,
596 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
597 The value is actually the element of LIST whose cdr is ELT.")
599 register Lisp_Object key
;
602 register Lisp_Object tail
;
603 for (tail
= list
; !NILP (tail
); tail
= Fcdr (tail
))
605 register Lisp_Object elt
, tem
;
607 if (!CONSP (elt
)) continue;
609 if (EQ (key
, tem
)) return elt
;
615 DEFUN ("delq", Fdelq
, Sdelq
, 2, 2, 0,
616 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
617 The modified LIST is returned. Comparison is done with `eq'.\n\
618 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
619 therefore, write `(setq foo (delq element foo))'\n\
620 to be sure of changing the value of `foo'.")
622 register Lisp_Object elt
;
625 register Lisp_Object tail
, prev
;
626 register Lisp_Object tem
;
638 Fsetcdr (prev
, Fcdr (tail
));
648 DEFUN ("delete", Fdelete
, Sdelete
, 2, 2, 0,
649 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
650 The modified LIST is returned. Comparison is done with `equal'.\n\
651 If the first member of LIST is ELT, deleting it is not a side effect;\n\
652 it is simply using a different list.\n\
653 Therefore, write `(setq foo (delete element foo))'\n\
654 to be sure of changing the value of `foo'.")
656 register Lisp_Object elt
;
659 register Lisp_Object tail
, prev
;
660 register Lisp_Object tem
;
667 if (! NILP (Fequal (elt
, tem
)))
672 Fsetcdr (prev
, Fcdr (tail
));
682 DEFUN ("nreverse", Fnreverse
, Snreverse
, 1, 1, 0,
683 "Reverse LIST by modifying cdr pointers.\n\
684 Returns the beginning of the reversed list.")
688 register Lisp_Object prev
, tail
, next
;
690 if (NILP (list
)) return list
;
697 Fsetcdr (tail
, prev
);
704 DEFUN ("reverse", Freverse
, Sreverse
, 1, 1, 0,
705 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
706 See also the function `nreverse', which is used more often.")
711 register Lisp_Object
*vec
;
712 register Lisp_Object tail
;
715 length
= Flength (list
);
716 vec
= (Lisp_Object
*) alloca (XINT (length
) * sizeof (Lisp_Object
));
717 for (i
= XINT (length
) - 1, tail
= list
; i
>= 0; i
--, tail
= Fcdr (tail
))
718 vec
[i
] = Fcar (tail
);
720 return Flist (XINT (length
), vec
);
723 Lisp_Object
merge ();
725 DEFUN ("sort", Fsort
, Ssort
, 2, 2, 0,
726 "Sort LIST, stably, comparing elements using PREDICATE.\n\
727 Returns the sorted list. LIST is modified by side effects.\n\
728 PREDICATE is called with two elements of LIST, and should return T\n\
729 if the first element is \"less\" than the second.")
731 Lisp_Object list
, pred
;
733 Lisp_Object front
, back
;
734 register Lisp_Object len
, tem
;
735 struct gcpro gcpro1
, gcpro2
;
739 len
= Flength (list
);
744 XSETINT (len
, (length
/ 2) - 1);
745 tem
= Fnthcdr (len
, list
);
749 GCPRO2 (front
, back
);
750 front
= Fsort (front
, pred
);
751 back
= Fsort (back
, pred
);
753 return merge (front
, back
, pred
);
757 merge (org_l1
, org_l2
, pred
)
758 Lisp_Object org_l1
, org_l2
;
762 register Lisp_Object tail
;
764 register Lisp_Object l1
, l2
;
765 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
;
772 /* It is sufficient to protect org_l1 and org_l2.
773 When l1 and l2 are updated, we copy the new values
774 back into the org_ vars. */
775 GCPRO4 (org_l1
, org_l2
, pred
, value
);
795 tem
= call2 (pred
, Fcar (l2
), Fcar (l1
));
816 DEFUN ("get", Fget
, Sget
, 2, 2, 0,
817 "Return the value of SYMBOL's PROPNAME property.\n\
818 This is the last VALUE stored with `(put SYMBOL PROPNAME VALUE)'.")
821 register Lisp_Object prop
;
823 register Lisp_Object tail
;
824 for (tail
= Fsymbol_plist (sym
); !NILP (tail
); tail
= Fcdr (Fcdr (tail
)))
826 register Lisp_Object tem
;
829 return Fcar (Fcdr (tail
));
834 DEFUN ("put", Fput
, Sput
, 3, 3, 0,
835 "Store SYMBOL's PROPNAME property with value VALUE.\n\
836 It can be retrieved with `(get SYMBOL PROPNAME)'.")
839 register Lisp_Object prop
;
842 register Lisp_Object tail
, prev
;
845 for (tail
= Fsymbol_plist (sym
); !NILP (tail
); tail
= Fcdr (Fcdr (tail
)))
847 register Lisp_Object tem
;
850 return Fsetcar (Fcdr (tail
), val
);
853 newcell
= Fcons (prop
, Fcons (val
, Qnil
));
855 Fsetplist (sym
, newcell
);
857 Fsetcdr (Fcdr (prev
), newcell
);
861 DEFUN ("equal", Fequal
, Sequal
, 2, 2, 0,
862 "T if two Lisp objects have similar structure and contents.\n\
863 They must have the same data type.\n\
864 Conses are compared by comparing the cars and the cdrs.\n\
865 Vectors and strings are compared element by element.\n\
866 Numbers are compared by value, but integers cannot equal floats.\n\
867 (Use `=' if you want integers and floats to be able to be equal.)\n\
868 Symbols must match exactly.")
870 register Lisp_Object o1
, o2
;
872 return internal_equal (o1
, o2
, 0) ? Qt
: Qnil
;
876 internal_equal (o1
, o2
, depth
)
877 register Lisp_Object o1
, o2
;
881 error ("Stack overflow in equal");
887 if (XTYPE (o1
) != XTYPE (o2
))
892 #ifdef LISP_FLOAT_TYPE
894 return (extract_float (o1
) == extract_float (o2
));
899 if (!internal_equal (XCONS (o1
)->car
, XCONS (o2
)->car
, depth
+ 1))
901 o1
= XCONS (o1
)->cdr
;
902 o2
= XCONS (o2
)->cdr
;
907 if (MISCP (o1
) && XMISC (o1
)->type
!= XMISC (o2
)->type
)
911 if (!internal_equal (OVERLAY_START (o1
), OVERLAY_START (o1
),
913 || !internal_equal (OVERLAY_END (o1
), OVERLAY_END (o1
),
916 o1
= XOVERLAY (o1
)->plist
;
917 o2
= XOVERLAY (o2
)->plist
;
922 return (XMARKER (o1
)->buffer
== XMARKER (o2
)->buffer
923 && (XMARKER (o1
)->buffer
== 0
924 || XMARKER (o1
)->bufpos
== XMARKER (o2
)->bufpos
));
928 case Lisp_Vectorlike
:
929 if ((VECTORP (o1
) && VECTORP (o2
))
931 (COMPILEDP (o1
) && COMPILEDP (o2
)))
934 if (XVECTOR (o1
)->size
!= XVECTOR (o2
)->size
)
936 for (index
= 0; index
< XVECTOR (o1
)->size
; index
++)
939 v1
= XVECTOR (o1
)->contents
[index
];
940 v2
= XVECTOR (o2
)->contents
[index
];
941 if (!internal_equal (v1
, v2
, depth
+ 1))
951 if (XSTRING (o1
)->size
!= XSTRING (o2
)->size
)
953 if (bcmp (XSTRING (o1
)->data
, XSTRING (o2
)->data
,
956 #ifdef USE_TEXT_PROPERTIES
957 /* If the strings have intervals, verify they match;
958 if not, they are unequal. */
959 if ((XSTRING (o1
)->intervals
!= 0 || XSTRING (o2
)->intervals
!= 0)
960 && ! compare_string_intervals (o1
, o2
))
969 DEFUN ("fillarray", Ffillarray
, Sfillarray
, 2, 2, 0,
970 "Store each element of ARRAY with ITEM. ARRAY is a vector or string.")
972 Lisp_Object array
, item
;
974 register int size
, index
, charval
;
978 register Lisp_Object
*p
= XVECTOR (array
)->contents
;
979 size
= XVECTOR (array
)->size
;
980 for (index
= 0; index
< size
; index
++)
983 else if (STRINGP (array
))
985 register unsigned char *p
= XSTRING (array
)->data
;
986 CHECK_NUMBER (item
, 1);
987 charval
= XINT (item
);
988 size
= XSTRING (array
)->size
;
989 for (index
= 0; index
< size
; index
++)
994 array
= wrong_type_argument (Qarrayp
, array
);
1006 Lisp_Object args
[2];
1009 return Fnconc (2, args
);
1011 return Fnconc (2, &s1
);
1012 #endif /* NO_ARG_ARRAY */
1015 DEFUN ("nconc", Fnconc
, Snconc
, 0, MANY
, 0,
1016 "Concatenate any number of lists by altering them.\n\
1017 Only the last argument is not altered, and need not be a list.")
1022 register int argnum
;
1023 register Lisp_Object tail
, tem
, val
;
1027 for (argnum
= 0; argnum
< nargs
; argnum
++)
1030 if (NILP (tem
)) continue;
1035 if (argnum
+ 1 == nargs
) break;
1038 tem
= wrong_type_argument (Qlistp
, tem
);
1047 tem
= args
[argnum
+ 1];
1048 Fsetcdr (tail
, tem
);
1050 args
[argnum
+ 1] = tail
;
1056 /* This is the guts of all mapping functions.
1057 Apply fn to each element of seq, one by one,
1058 storing the results into elements of vals, a C vector of Lisp_Objects.
1059 leni is the length of vals, which should also be the length of seq. */
1062 mapcar1 (leni
, vals
, fn
, seq
)
1065 Lisp_Object fn
, seq
;
1067 register Lisp_Object tail
;
1070 struct gcpro gcpro1
, gcpro2
, gcpro3
;
1072 /* Don't let vals contain any garbage when GC happens. */
1073 for (i
= 0; i
< leni
; i
++)
1076 GCPRO3 (dummy
, fn
, seq
);
1078 gcpro1
.nvars
= leni
;
1079 /* We need not explicitly protect `tail' because it is used only on lists, and
1080 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
1084 for (i
= 0; i
< leni
; i
++)
1086 dummy
= XVECTOR (seq
)->contents
[i
];
1087 vals
[i
] = call1 (fn
, dummy
);
1090 else if (STRINGP (seq
))
1092 for (i
= 0; i
< leni
; i
++)
1094 XSETFASTINT (dummy
, XSTRING (seq
)->data
[i
]);
1095 vals
[i
] = call1 (fn
, dummy
);
1098 else /* Must be a list, since Flength did not get an error */
1101 for (i
= 0; i
< leni
; i
++)
1103 vals
[i
] = call1 (fn
, Fcar (tail
));
1111 DEFUN ("mapconcat", Fmapconcat
, Smapconcat
, 3, 3, 0,
1112 "Apply FN to each element of SEQ, and concat the results as strings.\n\
1113 In between each pair of results, stick in SEP.\n\
1114 Thus, \" \" as SEP results in spaces between the values returned by FN.")
1116 Lisp_Object fn
, seq
, sep
;
1121 register Lisp_Object
*args
;
1123 struct gcpro gcpro1
;
1125 len
= Flength (seq
);
1127 nargs
= leni
+ leni
- 1;
1128 if (nargs
< 0) return build_string ("");
1130 args
= (Lisp_Object
*) alloca (nargs
* sizeof (Lisp_Object
));
1133 mapcar1 (leni
, args
, fn
, seq
);
1136 for (i
= leni
- 1; i
>= 0; i
--)
1137 args
[i
+ i
] = args
[i
];
1139 for (i
= 1; i
< nargs
; i
+= 2)
1142 return Fconcat (nargs
, args
);
1145 DEFUN ("mapcar", Fmapcar
, Smapcar
, 2, 2, 0,
1146 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
1147 The result is a list just as long as SEQUENCE.\n\
1148 SEQUENCE may be a list, a vector or a string.")
1150 Lisp_Object fn
, seq
;
1152 register Lisp_Object len
;
1154 register Lisp_Object
*args
;
1156 len
= Flength (seq
);
1157 leni
= XFASTINT (len
);
1158 args
= (Lisp_Object
*) alloca (leni
* sizeof (Lisp_Object
));
1160 mapcar1 (leni
, args
, fn
, seq
);
1162 return Flist (leni
, args
);
1165 /* Anything that calls this function must protect from GC! */
1167 DEFUN ("y-or-n-p", Fy_or_n_p
, Sy_or_n_p
, 1, 1, 0,
1168 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
1169 Takes one argument, which is the string to display to ask the question.\n\
1170 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
1171 No confirmation of the answer is requested; a single character is enough.\n\
1172 Also accepts Space to mean yes, or Delete to mean no.")
1176 register Lisp_Object obj
, key
, def
, answer_string
, map
;
1177 register int answer
;
1178 Lisp_Object xprompt
;
1179 Lisp_Object args
[2];
1180 int ocech
= cursor_in_echo_area
;
1181 struct gcpro gcpro1
, gcpro2
;
1183 map
= Fsymbol_value (intern ("query-replace-map"));
1185 CHECK_STRING (prompt
, 0);
1187 GCPRO2 (prompt
, xprompt
);
1192 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1195 Lisp_Object pane
, menu
;
1196 redisplay_preserve_echo_area ();
1197 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1198 Fcons (Fcons (build_string ("No"), Qnil
),
1200 menu
= Fcons (prompt
, pane
);
1201 obj
= Fx_popup_dialog (Qt
, menu
);
1202 answer
= !NILP (obj
);
1206 cursor_in_echo_area
= 1;
1207 message ("%s(y or n) ", XSTRING (xprompt
)->data
);
1209 obj
= read_filtered_event (1, 0, 0);
1210 cursor_in_echo_area
= 0;
1211 /* If we need to quit, quit with cursor_in_echo_area = 0. */
1214 key
= Fmake_vector (make_number (1), obj
);
1215 def
= Flookup_key (map
, key
);
1216 answer_string
= Fsingle_key_description (obj
);
1218 if (EQ (def
, intern ("skip")))
1223 else if (EQ (def
, intern ("act")))
1228 else if (EQ (def
, intern ("recenter")))
1234 else if (EQ (def
, intern ("quit")))
1236 /* We want to exit this command for exit-prefix,
1237 and this is the only way to do it. */
1238 else if (EQ (def
, intern ("exit-prefix")))
1243 /* If we don't clear this, then the next call to read_char will
1244 return quit_char again, and we'll enter an infinite loop. */
1249 if (EQ (xprompt
, prompt
))
1251 args
[0] = build_string ("Please answer y or n. ");
1253 xprompt
= Fconcat (2, args
);
1258 if (! noninteractive
)
1260 cursor_in_echo_area
= -1;
1261 message ("%s(y or n) %c", XSTRING (xprompt
)->data
, answer
? 'y' : 'n');
1262 cursor_in_echo_area
= ocech
;
1265 return answer
? Qt
: Qnil
;
1268 /* This is how C code calls `yes-or-no-p' and allows the user
1271 Anything that calls this function must protect from GC! */
1274 do_yes_or_no_p (prompt
)
1277 return call1 (intern ("yes-or-no-p"), prompt
);
1280 /* Anything that calls this function must protect from GC! */
1282 DEFUN ("yes-or-no-p", Fyes_or_no_p
, Syes_or_no_p
, 1, 1, 0,
1283 "Ask user a yes-or-no question. Return t if answer is yes.\n\
1284 Takes one argument, which is the string to display to ask the question.\n\
1285 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
1286 The user must confirm the answer with RET,\n\
1287 and can edit it until it as been confirmed.")
1291 register Lisp_Object ans
;
1292 Lisp_Object args
[2];
1293 struct gcpro gcpro1
;
1296 CHECK_STRING (prompt
, 0);
1299 if ((NILP (last_nonmenu_event
) || CONSP (last_nonmenu_event
))
1302 Lisp_Object pane
, menu
, obj
;
1303 redisplay_preserve_echo_area ();
1304 pane
= Fcons (Fcons (build_string ("Yes"), Qt
),
1305 Fcons (Fcons (build_string ("No"), Qnil
),
1308 menu
= Fcons (prompt
, pane
);
1309 obj
= Fx_popup_dialog (Qt
, menu
);
1316 args
[1] = build_string ("(yes or no) ");
1317 prompt
= Fconcat (2, args
);
1323 ans
= Fdowncase (Fread_from_minibuffer (prompt
, Qnil
, Qnil
, Qnil
,
1324 Qyes_or_no_p_history
));
1325 if (XSTRING (ans
)->size
== 3 && !strcmp (XSTRING (ans
)->data
, "yes"))
1330 if (XSTRING (ans
)->size
== 2 && !strcmp (XSTRING (ans
)->data
, "no"))
1338 message ("Please answer yes or no.");
1339 Fsleep_for (make_number (2), Qnil
);
1343 DEFUN ("load-average", Fload_average
, Sload_average
, 0, 0, 0,
1344 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
1345 Each of the three load averages is multiplied by 100,\n\
1346 then converted to integer.\n\
1347 If the 5-minute or 15-minute load averages are not available, return a\n\
1348 shortened list, containing only those averages which are available.")
1352 int loads
= getloadavg (load_ave
, 3);
1356 error ("load-average not implemented for this operating system");
1360 ret
= Fcons (make_number ((int) (load_ave
[--loads
] * 100.0)), ret
);
1365 Lisp_Object Vfeatures
;
1367 DEFUN ("featurep", Ffeaturep
, Sfeaturep
, 1, 1, 0,
1368 "Returns t if FEATURE is present in this Emacs.\n\
1369 Use this to conditionalize execution of lisp code based on the presence or\n\
1370 absence of emacs or environment extensions.\n\
1371 Use `provide' to declare that a feature is available.\n\
1372 This function looks at the value of the variable `features'.")
1374 Lisp_Object feature
;
1376 register Lisp_Object tem
;
1377 CHECK_SYMBOL (feature
, 0);
1378 tem
= Fmemq (feature
, Vfeatures
);
1379 return (NILP (tem
)) ? Qnil
: Qt
;
1382 DEFUN ("provide", Fprovide
, Sprovide
, 1, 1, 0,
1383 "Announce that FEATURE is a feature of the current Emacs.")
1385 Lisp_Object feature
;
1387 register Lisp_Object tem
;
1388 CHECK_SYMBOL (feature
, 0);
1389 if (!NILP (Vautoload_queue
))
1390 Vautoload_queue
= Fcons (Fcons (Vfeatures
, Qnil
), Vautoload_queue
);
1391 tem
= Fmemq (feature
, Vfeatures
);
1393 Vfeatures
= Fcons (feature
, Vfeatures
);
1394 LOADHIST_ATTACH (Fcons (Qprovide
, feature
));
1398 DEFUN ("require", Frequire
, Srequire
, 1, 2, 0,
1399 "If feature FEATURE is not loaded, load it from FILENAME.\n\
1400 If FEATURE is not a member of the list `features', then the feature\n\
1401 is not loaded; so load the file FILENAME.\n\
1402 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
1403 (feature
, file_name
)
1404 Lisp_Object feature
, file_name
;
1406 register Lisp_Object tem
;
1407 CHECK_SYMBOL (feature
, 0);
1408 tem
= Fmemq (feature
, Vfeatures
);
1409 LOADHIST_ATTACH (Fcons (Qrequire
, feature
));
1412 int count
= specpdl_ptr
- specpdl
;
1414 /* Value saved here is to be restored into Vautoload_queue */
1415 record_unwind_protect (un_autoload
, Vautoload_queue
);
1416 Vautoload_queue
= Qt
;
1418 Fload (NILP (file_name
) ? Fsymbol_name (feature
) : file_name
,
1421 tem
= Fmemq (feature
, Vfeatures
);
1423 error ("Required feature %s was not provided",
1424 XSYMBOL (feature
)->name
->data
);
1426 /* Once loading finishes, don't undo it. */
1427 Vautoload_queue
= Qt
;
1428 feature
= unbind_to (count
, feature
);
1435 Qstring_lessp
= intern ("string-lessp");
1436 staticpro (&Qstring_lessp
);
1437 Qprovide
= intern ("provide");
1438 staticpro (&Qprovide
);
1439 Qrequire
= intern ("require");
1440 staticpro (&Qrequire
);
1441 Qyes_or_no_p_history
= intern ("yes-or-no-p-history");
1442 staticpro (&Qyes_or_no_p_history
);
1444 DEFVAR_LISP ("features", &Vfeatures
,
1445 "A list of symbols which are the features of the executing emacs.\n\
1446 Used by `featurep' and `require', and altered by `provide'.");
1449 defsubr (&Sidentity
);
1452 defsubr (&Sstring_equal
);
1453 defsubr (&Sstring_lessp
);
1456 defsubr (&Svconcat
);
1457 defsubr (&Scopy_sequence
);
1458 defsubr (&Scopy_alist
);
1459 defsubr (&Ssubstring
);
1470 defsubr (&Snreverse
);
1471 defsubr (&Sreverse
);
1476 defsubr (&Sfillarray
);
1479 defsubr (&Smapconcat
);
1480 defsubr (&Sy_or_n_p
);
1481 defsubr (&Syes_or_no_p
);
1482 defsubr (&Sload_average
);
1483 defsubr (&Sfeaturep
);
1484 defsubr (&Srequire
);
1485 defsubr (&Sprovide
);