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