Mercurial > hg > xemacs-beta
comparison src/data.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 0293115a14e9 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 /* Primitive operations on Lisp data types for XEmacs Lisp interpreter. | |
2 Copyright (C) 1985, 1986, 1988, 1992, 1993, 1994, 1995 | |
3 Free Software Foundation, Inc. | |
4 | |
5 This file is part of XEmacs. | |
6 | |
7 XEmacs is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2, or (at your option) any | |
10 later version. | |
11 | |
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 /* Synched up with: Mule 2.0, FSF 19.30. Some of FSF's data.c is in | |
23 XEmacs' symbols.c. */ | |
24 | |
25 /* This file has been Mule-ized. */ | |
26 | |
27 #include <config.h> | |
28 #include "lisp.h" | |
29 | |
30 #include "buffer.h" | |
31 #include "bytecode.h" | |
32 | |
33 #include "syssignal.h" | |
34 #ifdef LISP_FLOAT_TYPE | |
35 /* Need to define a differentiating symbol -- see sysfloat.h */ | |
36 # define THIS_FILENAME data_c | |
37 # include "sysfloat.h" | |
38 #endif /* LISP_FLOAT_TYPE */ | |
39 | |
40 Lisp_Object Qnil, Qt, Qquote, Qlambda, Qunbound; | |
41 Lisp_Object Qerror_conditions, Qerror_message, Qtop_level; | |
42 Lisp_Object Qsignal, Qerror, Qquit, Qwrong_type_argument, Qargs_out_of_range; | |
43 Lisp_Object Qvoid_variable, Qcyclic_variable_indirection; | |
44 Lisp_Object Qvoid_function, Qcyclic_function_indirection; | |
45 Lisp_Object Qsetting_constant, Qinvalid_read_syntax; | |
46 Lisp_Object Qmalformed_list, Qmalformed_property_list; | |
47 Lisp_Object Qcircular_list, Qcircular_property_list; | |
48 Lisp_Object Qinvalid_function, Qwrong_number_of_arguments, Qno_catch; | |
49 Lisp_Object Qio_error, Qend_of_file; | |
50 Lisp_Object Qarith_error, Qrange_error, Qdomain_error; | |
51 Lisp_Object Qsingularity_error, Qoverflow_error, Qunderflow_error; | |
52 Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only; | |
53 Lisp_Object Qintegerp, Qnatnump, Qsymbolp, Qkeywordp, Qlistp, Qconsp, Qsubrp; | |
54 Lisp_Object Qcharacterp, Qstringp, Qarrayp, Qsequencep, Qbufferp; | |
55 Lisp_Object Qcompiled_functionp; | |
56 Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp; | |
57 Lisp_Object Qinteger_or_char_p, Qinteger_char_or_marker_p; | |
58 Lisp_Object Qbit_vectorp, Qbitp; | |
59 | |
60 /* Qstring, Qinteger, Qsymbol, Qvector defined in general.c */ | |
61 Lisp_Object Qcons, Qkeyword; | |
62 | |
63 Lisp_Object Qcdr; | |
64 | |
65 Lisp_Object Qignore; | |
66 | |
67 #ifdef LISP_FLOAT_TYPE | |
68 Lisp_Object Qfloatp; | |
69 #endif | |
70 Lisp_Object Qnumberp, Qnumber_or_marker_p, Qnumber_char_or_marker_p; | |
71 | |
72 Lisp_Object Qweak_listp; | |
73 | |
74 Lisp_Object | |
75 wrong_type_argument (Lisp_Object predicate, Lisp_Object value) | |
76 { | |
77 /* This function can GC */ | |
78 REGISTER Lisp_Object tem; | |
79 do | |
80 { | |
81 #ifdef MOCKLISP_SUPPORT | |
82 if (!EQ (Vmocklisp_arguments, Qt)) | |
83 { | |
84 if (STRINGP (value) && | |
85 (EQ (predicate, Qintegerp) || | |
86 EQ (predicate, Qinteger_or_marker_p) || | |
87 EQ (predicate, Qinteger_char_or_marker_p))) | |
88 return Fstring_to_number (value); | |
89 if (INTP (value) && EQ (predicate, Qstringp)) | |
90 return Fnumber_to_string (value); | |
91 if (CHARP (value) && EQ (predicate, Qstringp)) | |
92 return Fchar_to_string (value); | |
93 } | |
94 #endif | |
95 value = Fsignal (Qwrong_type_argument, list2 (predicate, value)); | |
96 tem = call1 (predicate, value); | |
97 } | |
98 while (NILP (tem)); | |
99 return value; | |
100 } | |
101 | |
102 DOESNT_RETURN | |
103 dead_wrong_type_argument (Lisp_Object predicate, Lisp_Object value) | |
104 { | |
105 signal_error (Qwrong_type_argument, list2 (predicate, value)); | |
106 } | |
107 | |
108 DEFUN ("wrong-type-argument", Fwrong_type_argument, Swrong_type_argument, | |
109 2, 2, 0 /* | |
110 Signal an error until the correct type value is given by the user. | |
111 This function loops, signalling a continuable `wrong-type-argument' error | |
112 with PREDICATE and VALUE as the data associated with the error and then | |
113 calling PREDICATE on the returned value, until the value gotten satisfies | |
114 PREDICATE. At that point, the gotten value is returned. | |
115 */ ) | |
116 (predicate, value) | |
117 Lisp_Object predicate, value; | |
118 { | |
119 return wrong_type_argument (predicate, value); | |
120 } | |
121 | |
122 DOESNT_RETURN | |
123 pure_write_error (void) | |
124 { | |
125 error ("Attempt to modify read-only object"); | |
126 } | |
127 | |
128 DOESNT_RETURN | |
129 args_out_of_range (Lisp_Object a1, Lisp_Object a2) | |
130 { | |
131 signal_error (Qargs_out_of_range, list2 (a1, a2)); | |
132 } | |
133 | |
134 DOESNT_RETURN | |
135 args_out_of_range_3 (Lisp_Object a1, Lisp_Object a2, Lisp_Object a3) | |
136 { | |
137 signal_error (Qargs_out_of_range, list3 (a1, a2, a3)); | |
138 } | |
139 | |
140 void | |
141 check_int_range (int val, int min, int max) | |
142 { | |
143 if (val < min || val > max) | |
144 args_out_of_range_3 (make_int (val), make_int (min), | |
145 make_int (max)); | |
146 } | |
147 | |
148 #ifndef make_int | |
149 Lisp_Object | |
150 make_int (EMACS_INT num) | |
151 { | |
152 Lisp_Object val; | |
153 /* Don't use XSETINT here -- it's defined in terms of make_int (). */ | |
154 XSETOBJ (val, Lisp_Int, num); | |
155 return val; | |
156 } | |
157 #endif /* ! defined (make_int) */ | |
158 | |
159 /* On some machines, XINT needs a temporary location. | |
160 Here it is, in case it is needed. */ | |
161 | |
162 EMACS_INT sign_extend_temp; | |
163 | |
164 /* On a few machines, XINT can only be done by calling this. */ | |
165 /* XEmacs: only used by m/convex.h */ | |
166 int sign_extend_lisp_int (EMACS_INT num); | |
167 int | |
168 sign_extend_lisp_int (EMACS_INT num) | |
169 { | |
170 if (num & (1L << (VALBITS - 1))) | |
171 return num | ((-1L) << VALBITS); | |
172 else | |
173 return num & ((1L << VALBITS) - 1); | |
174 } | |
175 | |
176 /* characters do not need to sign extend so there's no need for special | |
177 futzing like with ints. */ | |
178 Lisp_Object | |
179 make_char (Emchar num) | |
180 { | |
181 return make_int (num); | |
182 } | |
183 | |
184 /* Data type predicates */ | |
185 | |
186 DEFUN ("eq", Feq, Seq, 2, 2, 0 /* | |
187 T if the two args are the same Lisp object. | |
188 */ ) | |
189 (obj1, obj2) | |
190 Lisp_Object obj1, obj2; | |
191 { | |
192 if (EQ (obj1, obj2)) | |
193 return Qt; | |
194 return Qnil; | |
195 } | |
196 | |
197 DEFUN ("null", Fnull, Snull, 1, 1, 0 /* | |
198 T if OBJECT is nil. | |
199 */ ) | |
200 (object) | |
201 Lisp_Object object; | |
202 { | |
203 if (NILP (object)) | |
204 return Qt; | |
205 return Qnil; | |
206 } | |
207 | |
208 DEFUN ("consp", Fconsp, Sconsp, 1, 1, 0 /* | |
209 T if OBJECT is a cons cell. | |
210 */ ) | |
211 (object) | |
212 Lisp_Object object; | |
213 { | |
214 if (CONSP (object)) | |
215 return Qt; | |
216 return Qnil; | |
217 } | |
218 | |
219 DEFUN ("atom", Fatom, Satom, 1, 1, 0 /* | |
220 T if OBJECT is not a cons cell. This includes nil. | |
221 */ ) | |
222 (object) | |
223 Lisp_Object object; | |
224 { | |
225 if (CONSP (object)) | |
226 return Qnil; | |
227 return Qt; | |
228 } | |
229 | |
230 DEFUN ("listp", Flistp, Slistp, 1, 1, 0 /* | |
231 T if OBJECT is a list. This includes nil. | |
232 */ ) | |
233 (object) | |
234 Lisp_Object object; | |
235 { | |
236 if (CONSP (object) || NILP (object)) | |
237 return Qt; | |
238 return Qnil; | |
239 } | |
240 | |
241 DEFUN ("nlistp", Fnlistp, Snlistp, 1, 1, 0 /* | |
242 T if OBJECT is not a list. Lists include nil. | |
243 */ ) | |
244 (object) | |
245 Lisp_Object object; | |
246 { | |
247 if (CONSP (object) || NILP (object)) | |
248 return Qnil; | |
249 return Qt; | |
250 } | |
251 | |
252 DEFUN ("symbolp", Fsymbolp, Ssymbolp, 1, 1, 0 /* | |
253 T if OBJECT is a symbol. | |
254 */ ) | |
255 (object) | |
256 Lisp_Object object; | |
257 { | |
258 if (SYMBOLP (object)) | |
259 return Qt; | |
260 return Qnil; | |
261 } | |
262 | |
263 DEFUN ("keywordp", Fkeywordp, Skeywordp, 1, 1, 0 /* | |
264 T if OBJECT is a keyword. | |
265 */ ) | |
266 (object) | |
267 Lisp_Object object; | |
268 { | |
269 if (KEYWORDP (object)) | |
270 return Qt; | |
271 return Qnil; | |
272 } | |
273 | |
274 DEFUN ("vectorp", Fvectorp, Svectorp, 1, 1, 0 /* | |
275 T if OBJECT is a vector. | |
276 */ ) | |
277 (object) | |
278 Lisp_Object object; | |
279 { | |
280 if (VECTORP (object)) | |
281 return Qt; | |
282 return Qnil; | |
283 } | |
284 | |
285 DEFUN ("bit-vector-p", Fbit_vector_p, Sbit_vector_p, 1, 1, 0 /* | |
286 T if OBJECT is a bit vector. | |
287 */ ) | |
288 (object) | |
289 Lisp_Object object; | |
290 { | |
291 if (BIT_VECTORP (object)) | |
292 return Qt; | |
293 return Qnil; | |
294 } | |
295 | |
296 DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0 /* | |
297 T if OBJECT is a string. | |
298 */ ) | |
299 (object) | |
300 Lisp_Object object; | |
301 { | |
302 if (STRINGP (object)) | |
303 return Qt; | |
304 return Qnil; | |
305 } | |
306 | |
307 DEFUN ("arrayp", Farrayp, Sarrayp, 1, 1, 0 /* | |
308 T if OBJECT is an array (string, vector, or bit vector). | |
309 */ ) | |
310 (object) | |
311 Lisp_Object object; | |
312 { | |
313 if (VECTORP (object) || STRINGP (object) || BIT_VECTORP (object)) | |
314 return Qt; | |
315 return Qnil; | |
316 } | |
317 | |
318 DEFUN ("sequencep", Fsequencep, Ssequencep, 1, 1, 0 /* | |
319 T if OBJECT is a sequence (list or array). | |
320 */ ) | |
321 (object) | |
322 Lisp_Object object; | |
323 { | |
324 if (CONSP (object) || NILP (object) | |
325 || VECTORP (object) || STRINGP (object) || BIT_VECTORP (object)) | |
326 return Qt; | |
327 return Qnil; | |
328 } | |
329 | |
330 DEFUN ("markerp", Fmarkerp, Smarkerp, 1, 1, 0 /* | |
331 T if OBJECT is a marker (editor pointer). | |
332 */ ) | |
333 (object) | |
334 Lisp_Object object; | |
335 { | |
336 if (MARKERP (object)) | |
337 return Qt; | |
338 return Qnil; | |
339 } | |
340 | |
341 DEFUN ("subrp", Fsubrp, Ssubrp, 1, 1, 0 /* | |
342 T if OBJECT is a built-in function. | |
343 */ ) | |
344 (object) | |
345 Lisp_Object object; | |
346 { | |
347 if (SUBRP (object)) | |
348 return Qt; | |
349 return Qnil; | |
350 } | |
351 | |
352 DEFUN ("subr-min-args", Fsubr_min_args, Ssubr_min_args, 1, 1, 0 /* | |
353 Return minimum number of args built-in function SUBR may be called with. | |
354 */ ) | |
355 (subr) | |
356 Lisp_Object subr; | |
357 { | |
358 CHECK_SUBR (subr); | |
359 return make_int (XSUBR (subr)->min_args); | |
360 } | |
361 | |
362 DEFUN ("subr-max-args", Fsubr_max_args, Ssubr_max_args, 1, 1, 0 /* | |
363 Return maximum number of args built-in function SUBR may be called with, | |
364 or nil if it takes an arbitrary number of arguments (or is a special form). | |
365 */ ) | |
366 (subr) | |
367 Lisp_Object subr; | |
368 { | |
369 int nargs; | |
370 CHECK_SUBR (subr); | |
371 nargs = XSUBR (subr)->max_args; | |
372 if (nargs == MANY || nargs == UNEVALLED) | |
373 return Qnil; | |
374 else | |
375 return make_int (nargs); | |
376 } | |
377 | |
378 DEFUN ("compiled-function-p", Fcompiled_function_p, Scompiled_function_p, 1, 1, 0 /* | |
379 t if OBJECT is a byte-compiled function object. | |
380 */ ) | |
381 (object) | |
382 Lisp_Object object; | |
383 { | |
384 if (COMPILED_FUNCTIONP (object)) | |
385 return Qt; | |
386 return Qnil; | |
387 } | |
388 | |
389 | |
390 DEFUN ("characterp", Fcharacterp, Scharacterp, 1, 1, 0 /* | |
391 t if OBJECT is a character. | |
392 A character is an integer that can be inserted into a buffer with | |
393 `insert-char'. All integers are considered valid characters and are | |
394 modded with 256 to get the actual character to use. | |
395 */ ) | |
396 (object) | |
397 Lisp_Object object; | |
398 { | |
399 if (CHARP (object)) | |
400 return Qt; | |
401 return Qnil; | |
402 } | |
403 | |
404 DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0 /* | |
405 t if OBJECT is a character or a string. | |
406 */ ) | |
407 (object) | |
408 Lisp_Object object; | |
409 { | |
410 if (CHAR_OR_CHAR_INTP (object) || STRINGP (object)) | |
411 return Qt; | |
412 return Qnil; | |
413 } | |
414 | |
415 DEFUN ("integerp", Fintegerp, Sintegerp, 1, 1, 0 /* | |
416 t if OBJECT is an integer. | |
417 */ ) | |
418 (object) | |
419 Lisp_Object object; | |
420 { | |
421 if (INTP (object)) | |
422 return Qt; | |
423 return Qnil; | |
424 } | |
425 | |
426 DEFUN ("integer-or-marker-p", Finteger_or_marker_p, Sinteger_or_marker_p, | |
427 1, 1, 0 /* | |
428 t if OBJECT is an integer or a marker (editor pointer). | |
429 */ ) | |
430 (object) | |
431 Lisp_Object object; | |
432 { | |
433 if (INTP (object) || MARKERP (object)) | |
434 return Qt; | |
435 return Qnil; | |
436 } | |
437 | |
438 DEFUN ("natnump", Fnatnump, Snatnump, 1, 1, 0 /* | |
439 t if OBJECT is a nonnegative integer. | |
440 */ ) | |
441 (object) | |
442 Lisp_Object object; | |
443 { | |
444 if (NATNUMP (object)) | |
445 return Qt; | |
446 return Qnil; | |
447 } | |
448 | |
449 DEFUN ("bitp", Fbitp, Sbitp, 1, 1, 0 /* | |
450 t if OBJECT is a bit (0 or 1). | |
451 */ ) | |
452 (object) | |
453 Lisp_Object object; | |
454 { | |
455 if (BITP (object)) | |
456 return Qt; | |
457 return Qnil; | |
458 } | |
459 | |
460 DEFUN ("numberp", Fnumberp, Snumberp, 1, 1, 0 /* | |
461 t if OBJECT is a number (floating point or integer). | |
462 */ ) | |
463 (object) | |
464 Lisp_Object object; | |
465 { | |
466 if (INT_OR_FLOATP (object)) | |
467 return Qt; | |
468 return Qnil; | |
469 } | |
470 | |
471 DEFUN ("number-or-marker-p", Fnumber_or_marker_p, Snumber_or_marker_p, 1, 1, 0 /* | |
472 t if OBJECT is a number or a marker. | |
473 */ ) | |
474 (object) | |
475 Lisp_Object object; | |
476 { | |
477 if (INT_OR_FLOATP (object) | |
478 || MARKERP (object)) | |
479 return Qt; | |
480 return Qnil; | |
481 } | |
482 | |
483 #ifdef LISP_FLOAT_TYPE | |
484 DEFUN ("floatp", Ffloatp, Sfloatp, 1, 1, 0 /* | |
485 t if OBJECT is a floating point number. | |
486 */ ) | |
487 (object) | |
488 Lisp_Object object; | |
489 { | |
490 if (FLOATP (object)) | |
491 return Qt; | |
492 return Qnil; | |
493 } | |
494 #endif /* LISP_FLOAT_TYPE */ | |
495 | |
496 DEFUN ("type-of", Ftype_of, Stype_of, 1, 1, 0 /* | |
497 Return a symbol representing the type of OBJECT. | |
498 */ ) | |
499 (object) | |
500 Lisp_Object object; | |
501 { | |
502 if (CONSP (object)) | |
503 return Qcons; | |
504 if (SYMBOLP (object)) | |
505 return Qsymbol; | |
506 if (KEYWORDP (object)) | |
507 return Qkeyword; | |
508 if (INTP (object)) | |
509 return Qinteger; | |
510 if (STRINGP (object)) | |
511 return Qstring; | |
512 if (VECTORP (object)) | |
513 return Qvector; | |
514 assert (LRECORDP (object)); | |
515 return intern (XRECORD_LHEADER (object)->implementation->name); | |
516 } | |
517 | |
518 | |
519 /* Extract and set components of lists */ | |
520 | |
521 DEFUN ("car", Fcar, Scar, 1, 1, 0 /* | |
522 Return the car of LIST. If arg is nil, return nil. | |
523 Error if arg is not nil and not a cons cell. See also `car-safe'. | |
524 */ ) | |
525 (list) | |
526 Lisp_Object list; | |
527 { | |
528 while (1) | |
529 { | |
530 if (CONSP (list)) | |
531 return XCAR (list); | |
532 else if (NILP (list)) | |
533 return Qnil; | |
534 else | |
535 list = wrong_type_argument (Qconsp, list); | |
536 } | |
537 } | |
538 | |
539 DEFUN ("car-safe", Fcar_safe, Scar_safe, 1, 1, 0 /* | |
540 Return the car of OBJECT if it is a cons cell, or else nil. | |
541 */ ) | |
542 (object) | |
543 Lisp_Object object; | |
544 { | |
545 if (CONSP (object)) | |
546 return XCAR (object); | |
547 else | |
548 return Qnil; | |
549 } | |
550 | |
551 DEFUN ("cdr", Fcdr, Scdr, 1, 1, 0 /* | |
552 Return the cdr of LIST. If arg is nil, return nil. | |
553 Error if arg is not nil and not a cons cell. See also `cdr-safe'. | |
554 */ ) | |
555 (list) | |
556 Lisp_Object list; | |
557 { | |
558 while (1) | |
559 { | |
560 if (CONSP (list)) | |
561 return XCDR (list); | |
562 else if (NILP (list)) | |
563 return Qnil; | |
564 else | |
565 list = wrong_type_argument (Qconsp, list); | |
566 } | |
567 } | |
568 | |
569 DEFUN ("cdr-safe", Fcdr_safe, Scdr_safe, 1, 1, 0 /* | |
570 Return the cdr of OBJECT if it is a cons cell, or else nil. | |
571 */ ) | |
572 (object) | |
573 Lisp_Object object; | |
574 { | |
575 if (CONSP (object)) | |
576 return XCDR (object); | |
577 else | |
578 return Qnil; | |
579 } | |
580 | |
581 DEFUN ("setcar", Fsetcar, Ssetcar, 2, 2, 0 /* | |
582 Set the car of CONSCELL to be NEWCAR. Returns NEWCAR. | |
583 */ ) | |
584 (conscell, newcar) | |
585 Lisp_Object conscell, newcar; | |
586 { | |
587 if (!CONSP (conscell)) | |
588 conscell = wrong_type_argument (Qconsp, conscell); | |
589 | |
590 CHECK_IMPURE (conscell); | |
591 XCAR (conscell) = newcar; | |
592 return newcar; | |
593 } | |
594 | |
595 DEFUN ("setcdr", Fsetcdr, Ssetcdr, 2, 2, 0 /* | |
596 Set the cdr of CONSCELL to be NEWCDR. Returns NEWCDR. | |
597 */ ) | |
598 (conscell, newcdr) | |
599 Lisp_Object conscell, newcdr; | |
600 { | |
601 if (!CONSP (conscell)) | |
602 conscell = wrong_type_argument (Qconsp, conscell); | |
603 | |
604 CHECK_IMPURE (conscell); | |
605 XCDR (conscell) = newcdr; | |
606 return newcdr; | |
607 } | |
608 | |
609 /* Find the function at the end of a chain of symbol function indirections. */ | |
610 | |
611 /* If OBJECT is a symbol, find the end of its function chain and | |
612 return the value found there. If OBJECT is not a symbol, just | |
613 return it. If there is a cycle in the function chain, signal a | |
614 cyclic-function-indirection error. | |
615 | |
616 This is like Findirect_function, except that it doesn't signal an | |
617 error if the chain ends up unbound. */ | |
618 Lisp_Object | |
619 indirect_function (Lisp_Object object, int errorp) | |
620 { | |
621 Lisp_Object tortoise = object; | |
622 Lisp_Object hare = object; | |
623 | |
624 for (;;) | |
625 { | |
626 if (!SYMBOLP (hare) || UNBOUNDP (hare)) | |
627 break; | |
628 hare = XSYMBOL (hare)->function; | |
629 if (!SYMBOLP (hare) || UNBOUNDP (hare)) | |
630 break; | |
631 hare = XSYMBOL (hare)->function; | |
632 | |
633 tortoise = XSYMBOL (tortoise)->function; | |
634 | |
635 if (EQ (hare, tortoise)) | |
636 return (Fsignal (Qcyclic_function_indirection, list1 (object))); | |
637 } | |
638 | |
639 if (UNBOUNDP (hare) && errorp) | |
640 return Fsignal (Qvoid_function, list1 (object)); | |
641 return hare; | |
642 } | |
643 | |
644 DEFUN ("indirect-function", Findirect_function, Sindirect_function, 1, 1, 0 /* | |
645 Return the function at the end of OBJECT's function chain. | |
646 If OBJECT is a symbol, follow all function indirections and return | |
647 the final function binding. | |
648 If OBJECT is not a symbol, just return it. | |
649 Signal a void-function error if the final symbol is unbound. | |
650 Signal a cyclic-function-indirection error if there is a loop in the | |
651 function chain of symbols. | |
652 */ ) | |
653 (object) | |
654 Lisp_Object object; | |
655 { | |
656 return indirect_function (object, 1); | |
657 } | |
658 | |
659 /* Extract and set vector and string elements */ | |
660 | |
661 DEFUN ("aref", Faref, Saref, 2, 2, 0 /* | |
662 Return the element of ARRAY at index INDEX. | |
663 ARRAY may be a vector, bit vector, string, or byte-code object. | |
664 IDX starts at 0. | |
665 */ ) | |
666 (array, idx) | |
667 Lisp_Object array; | |
668 Lisp_Object idx; | |
669 { | |
670 int idxval; | |
671 | |
672 retry: | |
673 CHECK_INT_COERCE_CHAR (idx); /* yuck! */ | |
674 idxval = XINT (idx); | |
675 if (idxval < 0) | |
676 { | |
677 lose: | |
678 args_out_of_range (array, idx); | |
679 } | |
680 if (VECTORP (array)) | |
681 { | |
682 if (idxval >= vector_length (XVECTOR (array))) goto lose; | |
683 return vector_data (XVECTOR (array))[idxval]; | |
684 } | |
685 else if (BIT_VECTORP (array)) | |
686 { | |
687 if (idxval >= bit_vector_length (XBIT_VECTOR (array))) goto lose; | |
688 return make_int (bit_vector_bit (XBIT_VECTOR (array), idxval)); | |
689 } | |
690 else if (STRINGP (array)) | |
691 { | |
692 if (idxval >= string_char_length (XSTRING (array))) goto lose; | |
693 return (make_char (string_char (XSTRING (array), idxval))); | |
694 } | |
695 #ifdef LOSING_BYTECODE | |
696 else if (COMPILED_FUNCTIONP (array)) | |
697 { | |
698 /* Weird, gross compatibility kludge */ | |
699 return (Felt (array, idx)); | |
700 } | |
701 #endif | |
702 else | |
703 { | |
704 check_losing_bytecode ("aref", array); | |
705 array = wrong_type_argument (Qarrayp, array); | |
706 goto retry; | |
707 } | |
708 } | |
709 | |
710 DEFUN ("aset", Faset, Saset, 3, 3, 0 /* | |
711 Store into the element of ARRAY at index IDX the value NEWVAL. | |
712 ARRAY may be a vector, bit vector, or string. IDX starts at 0. | |
713 */ ) | |
714 (array, idx, newval) | |
715 Lisp_Object array; | |
716 Lisp_Object idx, newval; | |
717 { | |
718 int idxval; | |
719 | |
720 CHECK_INT_COERCE_CHAR (idx); /* yuck! */ | |
721 if (!VECTORP (array) && !BIT_VECTORP (array) && !STRINGP (array)) | |
722 array = wrong_type_argument (Qarrayp, array); | |
723 | |
724 idxval = XINT (idx); | |
725 if (idxval < 0) | |
726 { | |
727 lose: | |
728 args_out_of_range (array, idx); | |
729 } | |
730 CHECK_IMPURE (array); | |
731 | |
732 if (VECTORP (array)) | |
733 { | |
734 if (idxval >= vector_length (XVECTOR (array))) goto lose; | |
735 vector_data (XVECTOR (array))[idxval] = newval; | |
736 } | |
737 else if (BIT_VECTORP (array)) | |
738 { | |
739 if (idxval >= bit_vector_length (XBIT_VECTOR (array))) goto lose; | |
740 CHECK_BIT (newval); | |
741 set_bit_vector_bit (XBIT_VECTOR (array), idxval, !ZEROP (newval)); | |
742 } | |
743 else /* string */ | |
744 { | |
745 CHECK_CHAR_COERCE_INT (newval); | |
746 if (idxval >= string_char_length (XSTRING (array))) goto lose; | |
747 set_string_char (XSTRING (array), idxval, XCHAR (newval)); | |
748 bump_string_modiff (array); | |
749 } | |
750 | |
751 return newval; | |
752 } | |
753 | |
754 | |
755 /**********************************************************************/ | |
756 /* Compiled-function objects */ | |
757 /**********************************************************************/ | |
758 | |
759 /* The compiled_function->doc_and_interactive slot uses the minimal | |
760 number of conses, based on compiled_function->flags; it may take | |
761 any of the following forms: | |
762 | |
763 doc | |
764 interactive | |
765 domain | |
766 (doc . interactive) | |
767 (doc . domain) | |
768 (interactive . domain) | |
769 (doc . (interactive . domain)) | |
770 */ | |
771 | |
772 /* Caller must check flags.interactivep first */ | |
773 Lisp_Object | |
774 compiled_function_interactive (struct Lisp_Compiled_Function *b) | |
775 { | |
776 assert (b->flags.interactivep); | |
777 if (b->flags.documentationp && b->flags.domainp) | |
778 return (XCAR (XCDR (b->doc_and_interactive))); | |
779 else if (b->flags.documentationp) | |
780 return (XCDR (b->doc_and_interactive)); | |
781 else if (b->flags.domainp) | |
782 return (XCAR (b->doc_and_interactive)); | |
783 | |
784 /* if all else fails... */ | |
785 return (b->doc_and_interactive); | |
786 } | |
787 | |
788 /* Caller need not check flags.documentationp first */ | |
789 Lisp_Object | |
790 compiled_function_documentation (struct Lisp_Compiled_Function *b) | |
791 { | |
792 if (! b->flags.documentationp) | |
793 return Qnil; | |
794 else if (b->flags.interactivep && b->flags.domainp) | |
795 return (XCAR (b->doc_and_interactive)); | |
796 else if (b->flags.interactivep) | |
797 return (XCAR (b->doc_and_interactive)); | |
798 else if (b->flags.domainp) | |
799 return (XCAR (b->doc_and_interactive)); | |
800 else | |
801 return (b->doc_and_interactive); | |
802 } | |
803 | |
804 /* Caller need not check flags.domainp first */ | |
805 Lisp_Object | |
806 compiled_function_domain (struct Lisp_Compiled_Function *b) | |
807 { | |
808 if (! b->flags.domainp) | |
809 return Qnil; | |
810 else if (b->flags.documentationp && b->flags.interactivep) | |
811 return (XCDR (XCDR (b->doc_and_interactive))); | |
812 else if (b->flags.documentationp) | |
813 return (XCDR (b->doc_and_interactive)); | |
814 else if (b->flags.interactivep) | |
815 return (XCDR (b->doc_and_interactive)); | |
816 else | |
817 return (b->doc_and_interactive); | |
818 } | |
819 | |
820 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | |
821 | |
822 Lisp_Object | |
823 compiled_function_annotation (struct Lisp_Compiled_Function *b) | |
824 { | |
825 return b->annotated; | |
826 } | |
827 | |
828 #endif | |
829 | |
830 /* used only by Snarf-documentation; there must be doc already. */ | |
831 void | |
832 set_compiled_function_documentation (struct Lisp_Compiled_Function *b, | |
833 Lisp_Object new) | |
834 { | |
835 assert (b->flags.documentationp); | |
836 assert (INTP (new) || STRINGP (new)); | |
837 | |
838 if (b->flags.interactivep && b->flags.domainp) | |
839 XCAR (b->doc_and_interactive) = new; | |
840 else if (b->flags.interactivep) | |
841 XCAR (b->doc_and_interactive) = new; | |
842 else if (b->flags.domainp) | |
843 XCAR (b->doc_and_interactive) = new; | |
844 else | |
845 b->doc_and_interactive = new; | |
846 } | |
847 | |
848 DEFUN ("compiled-function-instructions", Fcompiled_function_instructions, | |
849 Scompiled_function_instructions, 1, 1, 0 /* | |
850 Return the byte-opcode string of the compiled-function object. | |
851 */ ) | |
852 (function) | |
853 Lisp_Object function; | |
854 { | |
855 CHECK_COMPILED_FUNCTION (function); | |
856 return (XCOMPILED_FUNCTION (function)->bytecodes); | |
857 } | |
858 | |
859 DEFUN ("compiled-function-constants", Fcompiled_function_constants, | |
860 Scompiled_function_constants, 1, 1, 0 /* | |
861 Return the constants vector of the compiled-function object. | |
862 */ ) | |
863 (function) | |
864 Lisp_Object function; | |
865 { | |
866 CHECK_COMPILED_FUNCTION (function); | |
867 return (XCOMPILED_FUNCTION (function)->constants); | |
868 } | |
869 | |
870 DEFUN ("compiled-function-stack-depth", Fcompiled_function_stack_depth, | |
871 Scompiled_function_stack_depth, 1, 1, 0 /* | |
872 Return the max stack depth of the compiled-function object. | |
873 */ ) | |
874 (function) | |
875 Lisp_Object function; | |
876 { | |
877 CHECK_COMPILED_FUNCTION (function); | |
878 return (make_int (XCOMPILED_FUNCTION (function)->maxdepth)); | |
879 } | |
880 | |
881 DEFUN ("compiled-function-arglist", Fcompiled_function_arglist, | |
882 Scompiled_function_arglist, 1, 1, 0 /* | |
883 Return the argument list of the compiled-function object. | |
884 */ ) | |
885 (function) | |
886 Lisp_Object function; | |
887 { | |
888 CHECK_COMPILED_FUNCTION (function); | |
889 return (XCOMPILED_FUNCTION (function)->arglist); | |
890 } | |
891 | |
892 DEFUN ("compiled-function-interactive", Fcompiled_function_interactive, | |
893 Scompiled_function_interactive, 1, 1, 0 /* | |
894 Return the interactive spec of the compiled-function object, or nil. | |
895 If non-nil, the return value will be a list whose first element is | |
896 `interactive' and whose second element is the interactive spec. | |
897 */ ) | |
898 (function) | |
899 Lisp_Object function; | |
900 { | |
901 CHECK_COMPILED_FUNCTION (function); | |
902 if (!XCOMPILED_FUNCTION (function)->flags.interactivep) | |
903 return Qnil; | |
904 return (list2 (Qinteractive, | |
905 compiled_function_interactive | |
906 (XCOMPILED_FUNCTION (function)))); | |
907 } | |
908 | |
909 DEFUN ("compiled-function-doc-string", Fcompiled_function_doc_string, | |
910 Scompiled_function_doc_string, 1, 1, 0 /* | |
911 Return the doc string of the compiled-function object, if available. | |
912 */ ) | |
913 (function) | |
914 Lisp_Object function; | |
915 { | |
916 CHECK_COMPILED_FUNCTION (function); | |
917 if (!XCOMPILED_FUNCTION (function)->flags.interactivep) | |
918 return Qnil; | |
919 return (list2 (Qinteractive, | |
920 compiled_function_interactive | |
921 (XCOMPILED_FUNCTION (function)))); | |
922 } | |
923 | |
924 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | |
925 | |
926 DEFUN ("compiled-function-annotation", Fcompiled_function_annotation, | |
927 Scompiled_function_annotation, 1, 1, 0 /* | |
928 Return the annotation of the compiled-function object, or nil. | |
929 The annotation is a piece of information indicating where this | |
930 compiled-function object came from. Generally this will be | |
931 a symbol naming a function; or a string naming a file, if the | |
932 compiled-function object was not defined in a function; or nil, | |
933 if the compiled-function object was not created as a result of | |
934 a `load'. | |
935 */ ) | |
936 (function) | |
937 Lisp_Object function; | |
938 { | |
939 CHECK_COMPILED_FUNCTION (function); | |
940 return (compiled_function_annotation (XCOMPILED_FUNCTION (function))); | |
941 } | |
942 | |
943 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ | |
944 | |
945 DEFUN ("compiled-function-domain", Fcompiled_function_domain, | |
946 Scompiled_function_domain, 1, 1, 0 /* | |
947 Return the domain of the compiled-function object, or nil. | |
948 This is only meaningful if I18N3 was enabled when emacs was compiled. | |
949 */ ) | |
950 (function) | |
951 Lisp_Object function; | |
952 { | |
953 CHECK_COMPILED_FUNCTION (function); | |
954 if (!XCOMPILED_FUNCTION (function)->flags.domainp) | |
955 return Qnil; | |
956 return (compiled_function_domain (XCOMPILED_FUNCTION (function))); | |
957 } | |
958 | |
959 | |
960 /**********************************************************************/ | |
961 /* Arithmetic functions */ | |
962 /**********************************************************************/ | |
963 | |
964 enum comparison { equal, notequal, less, grtr, less_or_equal, grtr_or_equal }; | |
965 | |
966 static Lisp_Object | |
967 arithcompare (Lisp_Object num1, Lisp_Object num2, | |
968 enum comparison comparison) | |
969 { | |
970 int floatp = 0; | |
971 | |
972 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (num1); | |
973 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (num2); | |
974 | |
975 #ifdef LISP_FLOAT_TYPE | |
976 if (FLOATP (num1) || FLOATP (num2)) | |
977 { | |
978 double f1, f2; | |
979 | |
980 floatp = 1; | |
981 f1 = (FLOATP (num1)) ? float_data (XFLOAT (num1)) : XINT (num1); | |
982 f2 = (FLOATP (num2)) ? float_data (XFLOAT (num2)) : XINT (num2); | |
983 | |
984 switch (comparison) | |
985 { | |
986 case equal: | |
987 if (f1 == f2) | |
988 return Qt; | |
989 return Qnil; | |
990 | |
991 case notequal: | |
992 if (f1 != f2) | |
993 return Qt; | |
994 return Qnil; | |
995 | |
996 case less: | |
997 if (f1 < f2) | |
998 return Qt; | |
999 return Qnil; | |
1000 | |
1001 case less_or_equal: | |
1002 if (f1 <= f2) | |
1003 return Qt; | |
1004 return Qnil; | |
1005 | |
1006 case grtr: | |
1007 if (f1 > f2) | |
1008 return Qt; | |
1009 return Qnil; | |
1010 | |
1011 case grtr_or_equal: | |
1012 if (f1 >= f2) | |
1013 return Qt; | |
1014 return Qnil; | |
1015 } | |
1016 } | |
1017 #endif /* LISP_FLOAT_TYPE */ | |
1018 else | |
1019 { | |
1020 switch (comparison) | |
1021 { | |
1022 case equal: | |
1023 if (XINT (num1) == XINT (num2)) | |
1024 return Qt; | |
1025 return Qnil; | |
1026 | |
1027 case notequal: | |
1028 if (XINT (num1) != XINT (num2)) | |
1029 return Qt; | |
1030 return Qnil; | |
1031 | |
1032 case less: | |
1033 if (XINT (num1) < XINT (num2)) | |
1034 return Qt; | |
1035 return Qnil; | |
1036 | |
1037 case less_or_equal: | |
1038 if (XINT (num1) <= XINT (num2)) | |
1039 return Qt; | |
1040 return Qnil; | |
1041 | |
1042 case grtr: | |
1043 if (XINT (num1) > XINT (num2)) | |
1044 return Qt; | |
1045 return Qnil; | |
1046 | |
1047 case grtr_or_equal: | |
1048 if (XINT (num1) >= XINT (num2)) | |
1049 return Qt; | |
1050 return Qnil; | |
1051 } | |
1052 } | |
1053 abort (); | |
1054 return Qnil; /* suppress compiler warning */ | |
1055 } | |
1056 | |
1057 DEFUN ("=", Feqlsign, Seqlsign, 2, 2, 0 /* | |
1058 T if two args, both numbers or markers, are equal. | |
1059 */ ) | |
1060 (num1, num2) | |
1061 Lisp_Object num1, num2; | |
1062 { | |
1063 return arithcompare (num1, num2, equal); | |
1064 } | |
1065 | |
1066 DEFUN ("<", Flss, Slss, 2, 2, 0 /* | |
1067 T if first arg is less than second arg. Both must be numbers or markers. | |
1068 */ ) | |
1069 (num1, num2) | |
1070 Lisp_Object num1, num2; | |
1071 { | |
1072 return arithcompare (num1, num2, less); | |
1073 } | |
1074 | |
1075 DEFUN (">", Fgtr, Sgtr, 2, 2, 0 /* | |
1076 T if first arg is greater than second arg. Both must be numbers or markers. | |
1077 */ ) | |
1078 (num1, num2) | |
1079 Lisp_Object num1, num2; | |
1080 { | |
1081 return arithcompare (num1, num2, grtr); | |
1082 } | |
1083 | |
1084 DEFUN ("<=", Fleq, Sleq, 2, 2, 0 /* | |
1085 T if first arg is less than or equal to second arg. | |
1086 Both must be numbers or markers. | |
1087 */ ) | |
1088 (num1, num2) | |
1089 Lisp_Object num1, num2; | |
1090 { | |
1091 return arithcompare (num1, num2, less_or_equal); | |
1092 } | |
1093 | |
1094 DEFUN (">=", Fgeq, Sgeq, 2, 2, 0 /* | |
1095 T if first arg is greater than or equal to second arg. | |
1096 Both must be numbers or markers. | |
1097 */ ) | |
1098 (num1, num2) | |
1099 Lisp_Object num1, num2; | |
1100 { | |
1101 return arithcompare (num1, num2, grtr_or_equal); | |
1102 } | |
1103 | |
1104 DEFUN ("/=", Fneq, Sneq, 2, 2, 0 /* | |
1105 T if first arg is not equal to second arg. Both must be numbers or markers. | |
1106 */ ) | |
1107 (num1, num2) | |
1108 Lisp_Object num1, num2; | |
1109 { | |
1110 return arithcompare (num1, num2, notequal); | |
1111 } | |
1112 | |
1113 DEFUN ("zerop", Fzerop, Szerop, 1, 1, 0 /* | |
1114 T if NUMBER is zero. | |
1115 */ ) | |
1116 (number) | |
1117 Lisp_Object number; | |
1118 { | |
1119 CHECK_INT_OR_FLOAT (number); | |
1120 | |
1121 #ifdef LISP_FLOAT_TYPE | |
1122 if (FLOATP (number)) | |
1123 { | |
1124 if (float_data (XFLOAT (number)) == 0.0) | |
1125 return Qt; | |
1126 return Qnil; | |
1127 } | |
1128 #endif /* LISP_FLOAT_TYPE */ | |
1129 | |
1130 if (XINT (number) == 0) | |
1131 return Qt; | |
1132 return Qnil; | |
1133 } | |
1134 | |
1135 /* Convert between a 32-bit value and a cons of two 16-bit values. | |
1136 This is used to pass 32-bit integers to and from the user. | |
1137 Use time_to_lisp() and lisp_to_time() for time values. | |
1138 | |
1139 If you're thinking of using this to store a pointer into a Lisp Object | |
1140 for internal purposes (such as when calling record_unwind_protect()), | |
1141 try using make_opaque_ptr()/get_opaque_ptr() instead. */ | |
1142 Lisp_Object | |
1143 word_to_lisp (unsigned int item) | |
1144 { | |
1145 return Fcons (make_int (item >> 16), make_int (item & 0xffff)); | |
1146 } | |
1147 | |
1148 unsigned int | |
1149 lisp_to_word (Lisp_Object item) | |
1150 { | |
1151 if (INTP (item)) | |
1152 return XINT (item); | |
1153 else | |
1154 { | |
1155 Lisp_Object top = Fcar (item); | |
1156 Lisp_Object bot = Fcdr (item); | |
1157 CHECK_INT (top); | |
1158 CHECK_INT (bot); | |
1159 return (XINT (top) << 16) | (XINT (bot) & 0xffff); | |
1160 } | |
1161 } | |
1162 | |
1163 | |
1164 DEFUN ("number-to-string", Fnumber_to_string, Snumber_to_string, 1, 1, 0 /* | |
1165 Convert NUM to a string by printing it in decimal. | |
1166 Uses a minus sign if negative. | |
1167 NUM may be an integer or a floating point number. | |
1168 */ ) | |
1169 (num) | |
1170 Lisp_Object num; | |
1171 { | |
1172 char buffer[VALBITS]; | |
1173 | |
1174 CHECK_INT_OR_FLOAT (num); | |
1175 | |
1176 #ifdef LISP_FLOAT_TYPE | |
1177 if (FLOATP (num)) | |
1178 { | |
1179 char pigbuf[350]; /* see comments in float_to_string */ | |
1180 | |
1181 float_to_string (pigbuf, float_data (XFLOAT (num))); | |
1182 return build_string (pigbuf); | |
1183 } | |
1184 #endif /* LISP_FLOAT_TYPE */ | |
1185 | |
1186 if (sizeof (int) == sizeof (EMACS_INT)) | |
1187 sprintf (buffer, "%d", XINT (num)); | |
1188 else if (sizeof (long) == sizeof (EMACS_INT)) | |
1189 sprintf (buffer, "%ld", (long) XINT (num)); | |
1190 else | |
1191 abort (); | |
1192 return build_string (buffer); | |
1193 } | |
1194 | |
1195 DEFUN ("string-to-number", Fstring_to_number, Sstring_to_number, 1, 1, 0 /* | |
1196 Convert STRING to a number by parsing it as a decimal number. | |
1197 This parses both integers and floating point numbers. | |
1198 It ignores leading spaces and tabs. | |
1199 */ ) | |
1200 (string) | |
1201 Lisp_Object string; | |
1202 { | |
1203 Lisp_Object value; | |
1204 char *p; | |
1205 CHECK_STRING (string); | |
1206 | |
1207 p = (char *) string_data (XSTRING (string)); | |
1208 /* Skip any whitespace at the front of the number. Some versions of | |
1209 atoi do this anyway, so we might as well make Emacs lisp consistent. */ | |
1210 while (*p == ' ' || *p == '\t') | |
1211 p++; | |
1212 | |
1213 #ifdef LISP_FLOAT_TYPE | |
1214 if (isfloat_string (p)) | |
1215 return make_float (atof (p)); | |
1216 #endif /* LISP_FLOAT_TYPE */ | |
1217 | |
1218 if (sizeof (int) == sizeof (EMACS_INT)) | |
1219 XSETINT (value, atoi (p)); | |
1220 else if (sizeof (long) == sizeof (EMACS_INT)) | |
1221 XSETINT (value, atol (p)); | |
1222 else | |
1223 abort (); | |
1224 return value; | |
1225 } | |
1226 | |
1227 enum arithop | |
1228 { Aadd, Asub, Amult, Adiv, Alogand, Alogior, Alogxor, Amax, Amin }; | |
1229 | |
1230 #ifdef LISP_FLOAT_TYPE | |
1231 static Lisp_Object float_arith_driver (double accum, int argnum, | |
1232 enum arithop code, | |
1233 int nargs, Lisp_Object *args); | |
1234 #endif | |
1235 | |
1236 | |
1237 static Lisp_Object | |
1238 arith_driver (enum arithop code, int nargs, Lisp_Object *args) | |
1239 { | |
1240 Lisp_Object val; | |
1241 REGISTER int argnum; | |
1242 REGISTER EMACS_INT accum = 0; | |
1243 REGISTER EMACS_INT next; | |
1244 | |
1245 switch (code) | |
1246 { | |
1247 case Alogior: | |
1248 case Alogxor: | |
1249 case Aadd: | |
1250 case Asub: | |
1251 accum = 0; break; | |
1252 case Amult: | |
1253 accum = 1; break; | |
1254 case Alogand: | |
1255 accum = -1; break; | |
1256 case Adiv: | |
1257 case Amax: | |
1258 case Amin: | |
1259 accum = 0; | |
1260 break; | |
1261 default: | |
1262 abort (); | |
1263 } | |
1264 | |
1265 for (argnum = 0; argnum < nargs; argnum++) | |
1266 { | |
1267 val = args[argnum]; /* using args[argnum] as argument to CHECK_INT_OR_FLOAT_... */ | |
1268 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (val); | |
1269 | |
1270 #ifdef LISP_FLOAT_TYPE | |
1271 if (FLOATP (val)) /* time to do serious math */ | |
1272 return (float_arith_driver ((double) accum, argnum, code, | |
1273 nargs, args)); | |
1274 #endif /* LISP_FLOAT_TYPE */ | |
1275 args[argnum] = val; /* runs into a compiler bug. */ | |
1276 next = XINT (args[argnum]); | |
1277 switch (code) | |
1278 { | |
1279 case Aadd: accum += next; break; | |
1280 case Asub: | |
1281 if (!argnum && nargs != 1) | |
1282 next = - next; | |
1283 accum -= next; | |
1284 break; | |
1285 case Amult: accum *= next; break; | |
1286 case Adiv: | |
1287 if (!argnum) accum = next; | |
1288 else | |
1289 { | |
1290 if (next == 0) | |
1291 Fsignal (Qarith_error, Qnil); | |
1292 accum /= next; | |
1293 } | |
1294 break; | |
1295 case Alogand: accum &= next; break; | |
1296 case Alogior: accum |= next; break; | |
1297 case Alogxor: accum ^= next; break; | |
1298 case Amax: if (!argnum || next > accum) accum = next; break; | |
1299 case Amin: if (!argnum || next < accum) accum = next; break; | |
1300 } | |
1301 } | |
1302 | |
1303 XSETINT (val, accum); | |
1304 return val; | |
1305 } | |
1306 | |
1307 #ifdef LISP_FLOAT_TYPE | |
1308 static Lisp_Object | |
1309 float_arith_driver (double accum, int argnum, enum arithop code, int nargs, | |
1310 Lisp_Object *args) | |
1311 { | |
1312 REGISTER Lisp_Object val; | |
1313 double next; | |
1314 | |
1315 for (; argnum < nargs; argnum++) | |
1316 { | |
1317 val = args[argnum]; /* using args[argnum] as argument to CHECK_INT_OR_FLOAT_... */ | |
1318 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (val); | |
1319 | |
1320 if (FLOATP (val)) | |
1321 { | |
1322 next = float_data (XFLOAT (val)); | |
1323 } | |
1324 else | |
1325 { | |
1326 args[argnum] = val; /* runs into a compiler bug. */ | |
1327 next = XINT (args[argnum]); | |
1328 } | |
1329 switch (code) | |
1330 { | |
1331 case Aadd: | |
1332 accum += next; | |
1333 break; | |
1334 case Asub: | |
1335 if (!argnum && nargs != 1) | |
1336 next = - next; | |
1337 accum -= next; | |
1338 break; | |
1339 case Amult: | |
1340 accum *= next; | |
1341 break; | |
1342 case Adiv: | |
1343 if (!argnum) | |
1344 accum = next; | |
1345 else | |
1346 { | |
1347 if (next == 0) | |
1348 Fsignal (Qarith_error, Qnil); | |
1349 accum /= next; | |
1350 } | |
1351 break; | |
1352 case Alogand: | |
1353 case Alogior: | |
1354 case Alogxor: | |
1355 return wrong_type_argument (Qinteger_or_marker_p, val); | |
1356 case Amax: | |
1357 if (!argnum || isnan (next) || next > accum) | |
1358 accum = next; | |
1359 break; | |
1360 case Amin: | |
1361 if (!argnum || isnan (next) || next < accum) | |
1362 accum = next; | |
1363 break; | |
1364 } | |
1365 } | |
1366 | |
1367 return make_float (accum); | |
1368 } | |
1369 #endif /* LISP_FLOAT_TYPE */ | |
1370 | |
1371 DEFUN ("+", Fplus, Splus, 0, MANY, 0 /* | |
1372 Return sum of any number of arguments, which are numbers or markers. | |
1373 */ ) | |
1374 (nargs, args) | |
1375 int nargs; | |
1376 Lisp_Object *args; | |
1377 { | |
1378 return arith_driver (Aadd, nargs, args); | |
1379 } | |
1380 | |
1381 DEFUN ("-", Fminus, Sminus, 0, MANY, 0 /* | |
1382 Negate number or subtract numbers or markers. | |
1383 With one arg, negates it. With more than one arg, | |
1384 subtracts all but the first from the first. | |
1385 */ ) | |
1386 (nargs, args) | |
1387 int nargs; | |
1388 Lisp_Object *args; | |
1389 { | |
1390 return arith_driver (Asub, nargs, args); | |
1391 } | |
1392 | |
1393 DEFUN ("*", Ftimes, Stimes, 0, MANY, 0 /* | |
1394 Return product of any number of arguments, which are numbers or markers. | |
1395 */ ) | |
1396 (nargs, args) | |
1397 int nargs; | |
1398 Lisp_Object *args; | |
1399 { | |
1400 return arith_driver (Amult, nargs, args); | |
1401 } | |
1402 | |
1403 DEFUN ("/", Fquo, Squo, 2, MANY, 0 /* | |
1404 Return first argument divided by all the remaining arguments. | |
1405 The arguments must be numbers or markers. | |
1406 */ ) | |
1407 (nargs, args) | |
1408 int nargs; | |
1409 Lisp_Object *args; | |
1410 { | |
1411 return arith_driver (Adiv, nargs, args); | |
1412 } | |
1413 | |
1414 DEFUN ("%", Frem, Srem, 2, 2, 0 /* | |
1415 Return remainder of first arg divided by second. | |
1416 Both must be integers or markers. | |
1417 */ ) | |
1418 (num1, num2) | |
1419 Lisp_Object num1, num2; | |
1420 { | |
1421 CHECK_INT_COERCE_CHAR_OR_MARKER (num1); | |
1422 CHECK_INT_COERCE_CHAR_OR_MARKER (num2); | |
1423 | |
1424 if (ZEROP (num2)) | |
1425 Fsignal (Qarith_error, Qnil); | |
1426 | |
1427 return (make_int (XINT (num1) % XINT (num2))); | |
1428 } | |
1429 | |
1430 /* Note, ANSI *requires* the presence of the fmod() library routine. | |
1431 If your system doesn't have it, complain to your vendor, because | |
1432 that is a bug. */ | |
1433 | |
1434 #ifndef HAVE_FMOD | |
1435 double | |
1436 fmod (double f1, double f2) | |
1437 { | |
1438 if (f2 < 0.0) | |
1439 f2 = -f2; | |
1440 return (f1 - f2 * floor (f1/f2)); | |
1441 } | |
1442 #endif /* ! HAVE_FMOD */ | |
1443 | |
1444 | |
1445 DEFUN ("mod", Fmod, Smod, 2, 2, 0 /* | |
1446 Return X modulo Y. | |
1447 The result falls between zero (inclusive) and Y (exclusive). | |
1448 Both X and Y must be numbers or markers. | |
1449 If either argument is a float, a float will be returned. | |
1450 */ ) | |
1451 (x, y) | |
1452 Lisp_Object x, y; | |
1453 { | |
1454 EMACS_INT i1, i2; | |
1455 | |
1456 #ifdef LISP_FLOAT_TYPE | |
1457 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (x); | |
1458 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (y); | |
1459 | |
1460 if (FLOATP (x) || FLOATP (y)) | |
1461 { | |
1462 double f1, f2; | |
1463 | |
1464 f1 = ((FLOATP (x)) ? float_data (XFLOAT (x)) : XINT (x)); | |
1465 f2 = ((FLOATP (y)) ? float_data (XFLOAT (y)) : XINT (y)); | |
1466 if (f2 == 0) | |
1467 Fsignal (Qarith_error, Qnil); | |
1468 | |
1469 f1 = fmod (f1, f2); | |
1470 | |
1471 /* If the "remainder" comes out with the wrong sign, fix it. */ | |
1472 if (f2 < 0 ? f1 > 0 : f1 < 0) | |
1473 f1 += f2; | |
1474 return (make_float (f1)); | |
1475 } | |
1476 #else /* not LISP_FLOAT_TYPE */ | |
1477 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (x); | |
1478 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (y); | |
1479 #endif /* not LISP_FLOAT_TYPE */ | |
1480 | |
1481 i1 = XINT (x); | |
1482 i2 = XINT (y); | |
1483 | |
1484 if (i2 == 0) | |
1485 Fsignal (Qarith_error, Qnil); | |
1486 | |
1487 i1 %= i2; | |
1488 | |
1489 /* If the "remainder" comes out with the wrong sign, fix it. */ | |
1490 if (i2 < 0 ? i1 > 0 : i1 < 0) | |
1491 i1 += i2; | |
1492 | |
1493 return (make_int (i1)); | |
1494 } | |
1495 | |
1496 | |
1497 DEFUN ("max", Fmax, Smax, 1, MANY, 0 /* | |
1498 Return largest of all the arguments (which must be numbers or markers). | |
1499 The value is always a number; markers are converted to numbers. | |
1500 */ ) | |
1501 (nargs, args) | |
1502 int nargs; | |
1503 Lisp_Object *args; | |
1504 { | |
1505 return arith_driver (Amax, nargs, args); | |
1506 } | |
1507 | |
1508 DEFUN ("min", Fmin, Smin, 1, MANY, 0 /* | |
1509 Return smallest of all the arguments (which must be numbers or markers). | |
1510 The value is always a number; markers are converted to numbers. | |
1511 */ ) | |
1512 (nargs, args) | |
1513 int nargs; | |
1514 Lisp_Object *args; | |
1515 { | |
1516 return arith_driver (Amin, nargs, args); | |
1517 } | |
1518 | |
1519 DEFUN ("logand", Flogand, Slogand, 0, MANY, 0 /* | |
1520 Return bitwise-and of all the arguments. | |
1521 Arguments may be integers, or markers converted to integers. | |
1522 */ ) | |
1523 (nargs, args) | |
1524 int nargs; | |
1525 Lisp_Object *args; | |
1526 { | |
1527 return arith_driver (Alogand, nargs, args); | |
1528 } | |
1529 | |
1530 DEFUN ("logior", Flogior, Slogior, 0, MANY, 0 /* | |
1531 Return bitwise-or of all the arguments. | |
1532 Arguments may be integers, or markers converted to integers. | |
1533 */ ) | |
1534 (nargs, args) | |
1535 int nargs; | |
1536 Lisp_Object *args; | |
1537 { | |
1538 return arith_driver (Alogior, nargs, args); | |
1539 } | |
1540 | |
1541 DEFUN ("logxor", Flogxor, Slogxor, 0, MANY, 0 /* | |
1542 Return bitwise-exclusive-or of all the arguments. | |
1543 Arguments may be integers, or markers converted to integers. | |
1544 */ ) | |
1545 (nargs, args) | |
1546 int nargs; | |
1547 Lisp_Object *args; | |
1548 { | |
1549 return arith_driver (Alogxor, nargs, args); | |
1550 } | |
1551 | |
1552 DEFUN ("ash", Fash, Sash, 2, 2, 0 /* | |
1553 Return VALUE with its bits shifted left by COUNT. | |
1554 If COUNT is negative, shifting is actually to the right. | |
1555 In this case, the sign bit is duplicated. | |
1556 */ ) | |
1557 (value, count) | |
1558 Lisp_Object value, count; | |
1559 { | |
1560 CHECK_INT_COERCE_CHAR (value); | |
1561 CHECK_INT (count); | |
1562 | |
1563 if (XINT (count) > 0) | |
1564 return (make_int (XINT (value) << XINT (count))); | |
1565 else | |
1566 return (make_int (XINT (value) >> -XINT (count))); | |
1567 } | |
1568 | |
1569 DEFUN ("lsh", Flsh, Slsh, 2, 2, 0 /* | |
1570 Return VALUE with its bits shifted left by COUNT. | |
1571 If COUNT is negative, shifting is actually to the right. | |
1572 In this case, zeros are shifted in on the left. | |
1573 */ ) | |
1574 (value, count) | |
1575 Lisp_Object value, count; | |
1576 { | |
1577 Lisp_Object val; | |
1578 | |
1579 CHECK_INT_COERCE_CHAR (value); | |
1580 CHECK_INT (count); | |
1581 | |
1582 if (XINT (count) > 0) | |
1583 XSETINT (val, (EMACS_UINT) XUINT (value) << XINT (count)); | |
1584 else | |
1585 XSETINT (val, (EMACS_UINT) XUINT (value) >> -XINT (count)); | |
1586 return val; | |
1587 } | |
1588 | |
1589 DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0 /* | |
1590 Return NUMBER plus one. NUMBER may be a number or a marker. | |
1591 Markers are converted to integers. | |
1592 */ ) | |
1593 (number) | |
1594 Lisp_Object number; | |
1595 { | |
1596 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (number); | |
1597 | |
1598 #ifdef LISP_FLOAT_TYPE | |
1599 if (FLOATP (number)) | |
1600 return (make_float (1.0 + float_data (XFLOAT (number)))); | |
1601 #endif /* LISP_FLOAT_TYPE */ | |
1602 | |
1603 return (make_int (XINT (number) + 1)); | |
1604 } | |
1605 | |
1606 DEFUN ("1-", Fsub1, Ssub1, 1, 1, 0 /* | |
1607 Return NUMBER minus one. NUMBER may be a number or a marker. | |
1608 Markers are converted to integers. | |
1609 */ ) | |
1610 (number) | |
1611 Lisp_Object number; | |
1612 { | |
1613 CHECK_INT_OR_FLOAT_COERCE_CHAR_OR_MARKER (number); | |
1614 | |
1615 #ifdef LISP_FLOAT_TYPE | |
1616 if (FLOATP (number)) | |
1617 return (make_float (-1.0 + (float_data (XFLOAT (number))))); | |
1618 #endif /* LISP_FLOAT_TYPE */ | |
1619 | |
1620 return (make_int (XINT (number) - 1)); | |
1621 } | |
1622 | |
1623 DEFUN ("lognot", Flognot, Slognot, 1, 1, 0 /* | |
1624 Return the bitwise complement of NUMBER. NUMBER must be an integer. | |
1625 */ ) | |
1626 (number) | |
1627 Lisp_Object number; | |
1628 { | |
1629 CHECK_INT (number); | |
1630 return (make_int (~XINT (number))); | |
1631 } | |
1632 | |
1633 | |
1634 /************************************************************************/ | |
1635 /* weak lists */ | |
1636 /************************************************************************/ | |
1637 | |
1638 /* A weak list is like a normal list except that elements automatically | |
1639 disappear when no longer in use, i.e. when no longer GC-protected. | |
1640 The basic idea is that we don't mark the elements during GC, but | |
1641 wait for them to be marked elsewhere. If they're not marked, we | |
1642 remove them. This is analogous to weak hashtables; see the explanation | |
1643 there for more info. */ | |
1644 | |
1645 static Lisp_Object mark_weak_list (Lisp_Object, void (*) (Lisp_Object)); | |
1646 static void print_weak_list (Lisp_Object, Lisp_Object, int); | |
1647 static int weak_list_equal (Lisp_Object, Lisp_Object, int depth); | |
1648 static unsigned long weak_list_hash (Lisp_Object obj, int depth); | |
1649 DEFINE_LRECORD_IMPLEMENTATION ("weak-list", weak_list, | |
1650 mark_weak_list, print_weak_list, | |
1651 0, weak_list_equal, weak_list_hash, | |
1652 struct weak_list); | |
1653 | |
1654 static Lisp_Object Vall_weak_lists; /* Gemarke es nicht!!! */ | |
1655 | |
1656 static Lisp_Object encode_weak_list_type (enum weak_list_type type); | |
1657 | |
1658 static Lisp_Object | |
1659 mark_weak_list (Lisp_Object obj, void (*markobj) (Lisp_Object)) | |
1660 { | |
1661 return Qnil; /* nichts ist gemarkt */ | |
1662 } | |
1663 | |
1664 static void | |
1665 print_weak_list (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) | |
1666 { | |
1667 if (print_readably) | |
1668 error ("printing unreadable object #<weak-list>"); | |
1669 | |
1670 write_c_string ("#<weak-list ", printcharfun); | |
1671 print_internal (encode_weak_list_type (XWEAK_LIST (obj)->type), | |
1672 printcharfun, 0); | |
1673 write_c_string (" ", printcharfun); | |
1674 print_internal (XWEAK_LIST (obj)->list, printcharfun, escapeflag); | |
1675 write_c_string (">", printcharfun); | |
1676 } | |
1677 | |
1678 static int | |
1679 weak_list_equal (Lisp_Object o1, Lisp_Object o2, int depth) | |
1680 { | |
1681 struct weak_list *w1 = XWEAK_LIST (o1); | |
1682 struct weak_list *w2 = XWEAK_LIST (o2); | |
1683 | |
1684 if (w1->type != w2->type || | |
1685 !internal_equal (w1->list, w2->list, depth + 1)) | |
1686 return 0; | |
1687 else | |
1688 return 1; | |
1689 } | |
1690 | |
1691 static unsigned long | |
1692 weak_list_hash (Lisp_Object obj, int depth) | |
1693 { | |
1694 struct weak_list *w = XWEAK_LIST (obj); | |
1695 | |
1696 return HASH2 ((unsigned long) w->type, | |
1697 internal_hash (w->list, depth + 1)); | |
1698 } | |
1699 | |
1700 Lisp_Object | |
1701 make_weak_list (enum weak_list_type type) | |
1702 { | |
1703 Lisp_Object result = Qnil; | |
1704 | |
1705 struct weak_list *wl = | |
1706 alloc_lcrecord (sizeof (struct weak_list), lrecord_weak_list); | |
1707 wl->list = Qnil; | |
1708 wl->type = type; | |
1709 XSETWEAK_LIST (result, wl); | |
1710 wl->next_weak = Vall_weak_lists; | |
1711 Vall_weak_lists = result; | |
1712 return result; | |
1713 } | |
1714 | |
1715 /* | |
1716 -- we do not mark the list elements (either the elements themselves | |
1717 or the cons cells that hold them) in the normal marking phase. | |
1718 -- at the end of marking, we go through all weak lists that are | |
1719 marked, and mark the cons cells that hold all marked | |
1720 objects, and possibly parts of the objects themselves. | |
1721 (See alloc.c, "after-mark".) | |
1722 -- after that, we prune away all the cons cells that are not marked. | |
1723 | |
1724 WARNING WARNING WARNING WARNING WARNING: | |
1725 | |
1726 The code in the following two functions is *unbelievably* tricky. | |
1727 Don't mess with it. You'll be sorry. | |
1728 | |
1729 Linked lists just majorly suck, d'ya know? | |
1730 */ | |
1731 | |
1732 int | |
1733 finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), | |
1734 void (*markobj) (Lisp_Object)) | |
1735 { | |
1736 Lisp_Object rest; | |
1737 int did_mark = 0; | |
1738 | |
1739 for (rest = Vall_weak_lists; | |
1740 !GC_NILP (rest); | |
1741 rest = XWEAK_LIST (rest)->next_weak) | |
1742 { | |
1743 Lisp_Object rest2; | |
1744 enum weak_list_type type = XWEAK_LIST (rest)->type; | |
1745 | |
1746 if (! ((*obj_marked_p) (rest))) | |
1747 /* The weak list is probably garbage. Ignore it. */ | |
1748 continue; | |
1749 | |
1750 for (rest2 = XWEAK_LIST (rest)->list; | |
1751 /* We need to be trickier since we're inside of GC; | |
1752 use CONSP instead of !NILP in case of user-visible | |
1753 imperfect lists */ | |
1754 GC_CONSP (rest2); | |
1755 rest2 = XCDR (rest2)) | |
1756 { | |
1757 Lisp_Object elem; | |
1758 /* If the element is "marked" (meaning depends on the type | |
1759 of weak list), we need to mark the cons containing the | |
1760 element, and maybe the element itself (if only some part | |
1761 was already marked). */ | |
1762 int need_to_mark_cons = 0; | |
1763 int need_to_mark_elem = 0; | |
1764 | |
1765 /* If a cons is already marked, then its car is already marked | |
1766 (either because of an external pointer or because of | |
1767 a previous call to this function), and likewise for all | |
1768 the rest of the elements in the list, so we can stop now. */ | |
1769 if ((*obj_marked_p) (rest2)) | |
1770 break; | |
1771 | |
1772 elem = XCAR (rest2); | |
1773 | |
1774 switch (type) | |
1775 { | |
1776 case WEAK_LIST_SIMPLE: | |
1777 if ((*obj_marked_p) (elem)) | |
1778 need_to_mark_cons = 1; | |
1779 break; | |
1780 | |
1781 case WEAK_LIST_ASSOC: | |
1782 if (!GC_CONSP (elem)) | |
1783 { | |
1784 /* just leave bogus elements there */ | |
1785 need_to_mark_cons = 1; | |
1786 need_to_mark_elem = 1; | |
1787 } | |
1788 else if ((*obj_marked_p) (XCAR (elem)) && | |
1789 (*obj_marked_p) (XCDR (elem))) | |
1790 { | |
1791 need_to_mark_cons = 1; | |
1792 /* We still need to mark elem, because it's | |
1793 probably not marked. */ | |
1794 need_to_mark_elem = 1; | |
1795 } | |
1796 break; | |
1797 | |
1798 case WEAK_LIST_KEY_ASSOC: | |
1799 if (!GC_CONSP (elem)) | |
1800 { | |
1801 /* just leave bogus elements there */ | |
1802 need_to_mark_cons = 1; | |
1803 need_to_mark_elem = 1; | |
1804 } | |
1805 else if ((*obj_marked_p) (XCAR (elem))) | |
1806 { | |
1807 need_to_mark_cons = 1; | |
1808 /* We still need to mark elem and XCDR (elem); | |
1809 marking elem does both */ | |
1810 need_to_mark_elem = 1; | |
1811 } | |
1812 break; | |
1813 | |
1814 case WEAK_LIST_VALUE_ASSOC: | |
1815 if (!GC_CONSP (elem)) | |
1816 { | |
1817 /* just leave bogus elements there */ | |
1818 need_to_mark_cons = 1; | |
1819 need_to_mark_elem = 1; | |
1820 } | |
1821 else if ((*obj_marked_p) (XCDR (elem))) | |
1822 { | |
1823 need_to_mark_cons = 1; | |
1824 /* We still need to mark elem and XCAR (elem); | |
1825 marking elem does both */ | |
1826 need_to_mark_elem = 1; | |
1827 } | |
1828 break; | |
1829 | |
1830 default: | |
1831 abort (); | |
1832 } | |
1833 | |
1834 if (need_to_mark_elem && ! (*obj_marked_p) (elem)) | |
1835 { | |
1836 (*markobj) (elem); | |
1837 did_mark = 1; | |
1838 } | |
1839 | |
1840 /* We also need to mark the cons that holds the elem or | |
1841 assoc-pair. We do *not* want to call (markobj) here | |
1842 because that will mark the entire list; we just want to | |
1843 mark the cons itself. | |
1844 */ | |
1845 if (need_to_mark_cons) | |
1846 { | |
1847 struct Lisp_Cons *ptr = XCONS (rest2); | |
1848 if (!CONS_MARKED_P (ptr)) | |
1849 { | |
1850 MARK_CONS (ptr); | |
1851 did_mark = 1; | |
1852 } | |
1853 } | |
1854 } | |
1855 | |
1856 /* In case of imperfect list, need to mark the final cons | |
1857 because we're not removing it */ | |
1858 if (!GC_NILP (rest2) && ! (obj_marked_p) (rest2)) | |
1859 { | |
1860 (markobj) (rest2); | |
1861 did_mark = 1; | |
1862 } | |
1863 } | |
1864 | |
1865 return did_mark; | |
1866 } | |
1867 | |
1868 void | |
1869 prune_weak_lists (int (*obj_marked_p) (Lisp_Object)) | |
1870 { | |
1871 Lisp_Object rest, prev = Qnil; | |
1872 | |
1873 for (rest = Vall_weak_lists; | |
1874 !GC_NILP (rest); | |
1875 rest = XWEAK_LIST (rest)->next_weak) | |
1876 { | |
1877 if (! ((*obj_marked_p) (rest))) | |
1878 { | |
1879 /* This weak list itself is garbage. Remove it from the list. */ | |
1880 if (GC_NILP (prev)) | |
1881 Vall_weak_lists = XWEAK_LIST (rest)->next_weak; | |
1882 else | |
1883 XWEAK_LIST (prev)->next_weak = | |
1884 XWEAK_LIST (rest)->next_weak; | |
1885 } | |
1886 else | |
1887 { | |
1888 Lisp_Object rest2, prev2 = Qnil; | |
1889 Lisp_Object tortoise; | |
1890 int go_tortoise = 0; | |
1891 | |
1892 for (rest2 = XWEAK_LIST (rest)->list, tortoise = rest2; | |
1893 /* We need to be trickier since we're inside of GC; | |
1894 use CONSP instead of !NILP in case of user-visible | |
1895 imperfect lists */ | |
1896 GC_CONSP (rest2);) | |
1897 { | |
1898 /* It suffices to check the cons for marking, | |
1899 regardless of the type of weak list: | |
1900 | |
1901 -- if the cons is pointed to somewhere else, | |
1902 then it should stay around and will be marked. | |
1903 -- otherwise, if it should stay around, it will | |
1904 have been marked in finish_marking_weak_lists(). | |
1905 -- otherwise, it's not marked and should disappear. | |
1906 */ | |
1907 if (!(*obj_marked_p) (rest2)) | |
1908 { | |
1909 /* bye bye :-( */ | |
1910 if (GC_NILP (prev2)) | |
1911 XWEAK_LIST (rest)->list = XCDR (rest2); | |
1912 else | |
1913 XCDR (prev2) = XCDR (rest2); | |
1914 rest2 = XCDR (rest2); | |
1915 /* Ouch. Circularity checking is even trickier | |
1916 than I thought. When we cut out a link | |
1917 like this, we can't advance the turtle or | |
1918 it'll catch up to us. Imagine that we're | |
1919 standing on floor tiles and moving forward -- | |
1920 what we just did here is as if the floor | |
1921 tile under us just disappeared and all the | |
1922 ones ahead of us slid one tile towards us. | |
1923 In other words, we didn't move at all; | |
1924 if the tortoise was one step behind us | |
1925 previously, it still is, and therefore | |
1926 it must not move. */ | |
1927 } | |
1928 else | |
1929 { | |
1930 prev2 = rest2; | |
1931 | |
1932 /* Implementing circularity checking is trickier here | |
1933 than in other places because we have to guarantee | |
1934 that we've processed all elements before exiting | |
1935 due to a circularity. (In most places, an error | |
1936 is issued upon encountering a circularity, so it | |
1937 doesn't really matter if all elements are processed.) | |
1938 The idea is that we process along with the hare | |
1939 rather than the tortoise. If at any point in | |
1940 our forward process we encounter the tortoise, | |
1941 we must have already visited the spot, so we exit. | |
1942 (If we process with the tortoise, we can fail to | |
1943 process cases where a cons points to itself, or | |
1944 where cons A points to cons B, which points to | |
1945 cons A.) */ | |
1946 | |
1947 rest2 = XCDR (rest2); | |
1948 if (go_tortoise) | |
1949 tortoise = XCDR (tortoise); | |
1950 go_tortoise = !go_tortoise; | |
1951 if (GC_EQ (rest2, tortoise)) | |
1952 break; | |
1953 } | |
1954 } | |
1955 | |
1956 prev = rest; | |
1957 } | |
1958 } | |
1959 } | |
1960 | |
1961 static enum weak_list_type | |
1962 decode_weak_list_type (Lisp_Object symbol) | |
1963 { | |
1964 CHECK_SYMBOL (symbol); | |
1965 if (EQ (symbol, Qsimple)) | |
1966 return WEAK_LIST_SIMPLE; | |
1967 if (EQ (symbol, Qassoc)) | |
1968 return WEAK_LIST_ASSOC; | |
1969 if (EQ (symbol, Qkey_assoc)) | |
1970 return WEAK_LIST_KEY_ASSOC; | |
1971 if (EQ (symbol, Qvalue_assoc)) | |
1972 return WEAK_LIST_VALUE_ASSOC; | |
1973 | |
1974 signal_simple_error ("Invalid weak list type", symbol); | |
1975 return WEAK_LIST_SIMPLE; /* not reached */ | |
1976 } | |
1977 | |
1978 static Lisp_Object | |
1979 encode_weak_list_type (enum weak_list_type type) | |
1980 { | |
1981 switch (type) | |
1982 { | |
1983 case WEAK_LIST_SIMPLE: | |
1984 return Qsimple; | |
1985 case WEAK_LIST_ASSOC: | |
1986 return Qassoc; | |
1987 case WEAK_LIST_KEY_ASSOC: | |
1988 return Qkey_assoc; | |
1989 case WEAK_LIST_VALUE_ASSOC: | |
1990 return Qvalue_assoc; | |
1991 default: | |
1992 abort (); | |
1993 } | |
1994 | |
1995 return Qnil; | |
1996 } | |
1997 | |
1998 DEFUN ("weak-list-p", Fweak_list_p, Sweak_list_p, 1, 1, 0 /* | |
1999 Return non-nil if OBJECT is a weak list. | |
2000 */ ) | |
2001 (object) | |
2002 Lisp_Object object; | |
2003 { | |
2004 return WEAK_LISTP (object) ? Qt : Qnil; | |
2005 } | |
2006 | |
2007 DEFUN ("make-weak-list", Fmake_weak_list, Smake_weak_list, 0, 1, 0 /* | |
2008 Create a new weak list. | |
2009 A weak list object is an object that contains a list. This list behaves | |
2010 like any other list except that its elements do not count towards | |
2011 garbage collection -- if the only pointer to an object in inside a weak | |
2012 list (other than pointers in similar objects such as weak hash tables), | |
2013 the object is garbage collected and automatically removed from the list. | |
2014 This is used internally, for example, to manage the list holding the | |
2015 children of an extent -- an extent that is unused but has a parent will | |
2016 still be reclaimed, and will automatically be removed from its parent's | |
2017 list of children. | |
2018 | |
2019 Optional argument TYPE specifies the type of the weak list, and defaults | |
2020 to `simple'. Recognized types are | |
2021 | |
2022 `simple' Objects in the list disappear if not pointed to. | |
2023 `assoc' Objects in the list disappear if they are conses | |
2024 and either the car or the cdr of the cons is not | |
2025 pointed to. | |
2026 `key-assoc' Objects in the list disappear if they are conses | |
2027 and the car is not pointed to. | |
2028 `value-assoc' Objects in the list disappear if they are conses | |
2029 and the cdr is not pointed to. | |
2030 */ ) | |
2031 (type) | |
2032 Lisp_Object type; | |
2033 { | |
2034 if (NILP (type)) | |
2035 type = Qsimple; | |
2036 | |
2037 return make_weak_list (decode_weak_list_type (type)); | |
2038 } | |
2039 | |
2040 DEFUN ("weak-list-type", Fweak_list_type, Sweak_list_type, 1, 1, 0 /* | |
2041 Return the type of the given weak-list object. | |
2042 */ ) | |
2043 (weak) | |
2044 Lisp_Object weak; | |
2045 { | |
2046 CHECK_WEAK_LIST (weak); | |
2047 return encode_weak_list_type (XWEAK_LIST (weak)->type); | |
2048 } | |
2049 | |
2050 DEFUN ("weak-list-list", Fweak_list_list, Sweak_list_list, 1, 1, 0 /* | |
2051 Return the list contained in a weak-list object. | |
2052 */ ) | |
2053 (weak) | |
2054 Lisp_Object weak; | |
2055 { | |
2056 CHECK_WEAK_LIST (weak); | |
2057 return XWEAK_LIST_LIST (weak); | |
2058 } | |
2059 | |
2060 DEFUN ("set-weak-list-list", Fset_weak_list_list, Sset_weak_list_list, | |
2061 2, 2, 0 /* | |
2062 Change the list contained in a weak-list object. | |
2063 */ ) | |
2064 (weak, new_list) | |
2065 Lisp_Object weak, new_list; | |
2066 { | |
2067 CHECK_WEAK_LIST (weak); | |
2068 XWEAK_LIST_LIST (weak) = new_list; | |
2069 return new_list; | |
2070 } | |
2071 | |
2072 | |
2073 /************************************************************************/ | |
2074 /* initialization */ | |
2075 /************************************************************************/ | |
2076 | |
2077 static SIGTYPE | |
2078 arith_error (int signo) | |
2079 { | |
2080 EMACS_REESTABLISH_SIGNAL (signo, arith_error); | |
2081 EMACS_UNBLOCK_SIGNAL (signo); | |
2082 signal_error (Qarith_error, Qnil); | |
2083 } | |
2084 | |
2085 void | |
2086 init_data_very_early (void) | |
2087 { | |
2088 /* Don't do this if just dumping out. | |
2089 We don't want to call `signal' in this case | |
2090 so that we don't have trouble with dumping | |
2091 signal-delivering routines in an inconsistent state. */ | |
2092 #ifndef CANNOT_DUMP | |
2093 if (!initialized) | |
2094 return; | |
2095 #endif /* CANNOT_DUMP */ | |
2096 signal (SIGFPE, arith_error); | |
2097 #ifdef uts | |
2098 signal (SIGEMT, arith_error); | |
2099 #endif /* uts */ | |
2100 } | |
2101 | |
2102 void | |
2103 init_errors_once_early (void) | |
2104 { | |
2105 defsymbol (&Qerror_conditions, "error-conditions"); | |
2106 defsymbol (&Qerror_message, "error-message"); | |
2107 | |
2108 /* We declare the errors here because some other deferrors depend | |
2109 on some of the errors below. */ | |
2110 | |
2111 /* ERROR is used as a signaler for random errors for which nothing | |
2112 else is right */ | |
2113 | |
2114 deferror (&Qerror, "error", "error", Qnil); | |
2115 deferror (&Qquit, "quit", "Quit", Qnil); | |
2116 | |
2117 deferror (&Qwrong_type_argument, "wrong-type-argument", | |
2118 "Wrong type argument", Qerror); | |
2119 deferror (&Qargs_out_of_range, "args-out-of-range", "Args out of range", | |
2120 Qerror); | |
2121 deferror (&Qvoid_function, "void-function", | |
2122 "Symbol's function definition is void", Qerror); | |
2123 deferror (&Qcyclic_function_indirection, "cyclic-function-indirection", | |
2124 "Symbol's chain of function indirections contains a loop", Qerror); | |
2125 deferror (&Qvoid_variable, "void-variable", | |
2126 "Symbol's value as variable is void", Qerror); | |
2127 deferror (&Qcyclic_variable_indirection, "cyclic-variable-indirection", | |
2128 "Symbol's chain of variable indirections contains a loop", Qerror); | |
2129 deferror (&Qsetting_constant, "setting-constant", | |
2130 "Attempt to set a constant symbol", Qerror); | |
2131 deferror (&Qinvalid_read_syntax, "invalid-read-syntax", | |
2132 "Invalid read syntax", Qerror); | |
2133 deferror (&Qmalformed_list, "malformed-list", | |
2134 "Malformed list", Qerror); | |
2135 deferror (&Qmalformed_property_list, "malformed-property-list", | |
2136 "Malformed property list", Qerror); | |
2137 deferror (&Qcircular_list, "circular-list", | |
2138 "Circular list", Qerror); | |
2139 deferror (&Qcircular_property_list, "circular-property-list", | |
2140 "Circular property list", Qerror); | |
2141 deferror (&Qinvalid_function, "invalid-function", "Invalid function", | |
2142 Qerror); | |
2143 deferror (&Qwrong_number_of_arguments, "wrong-number-of-arguments", | |
2144 "Wrong number of arguments", Qerror); | |
2145 deferror (&Qno_catch, "no-catch", "No catch for tag", | |
2146 Qerror); | |
2147 deferror (&Qbeginning_of_buffer, "beginning-of-buffer", | |
2148 "Beginning of buffer", Qerror); | |
2149 deferror (&Qend_of_buffer, "end-of-buffer", "End of buffer", Qerror); | |
2150 deferror (&Qbuffer_read_only, "buffer-read-only", "Buffer is read-only", | |
2151 Qerror); | |
2152 | |
2153 deferror (&Qio_error, "io-error", "IO Error", Qerror); | |
2154 deferror (&Qend_of_file, "end-of-file", "End of stream", Qio_error); | |
2155 | |
2156 deferror (&Qarith_error, "arith-error", "Arithmetic error", Qerror); | |
2157 deferror (&Qrange_error, "range-error", "Arithmetic range error", | |
2158 Qarith_error); | |
2159 deferror (&Qdomain_error, "domain-error", "Arithmetic domain error", | |
2160 Qarith_error); | |
2161 deferror (&Qsingularity_error, "singularity-error", | |
2162 "Arithmetic singularity error", Qdomain_error); | |
2163 deferror (&Qoverflow_error, "overflow-error", | |
2164 "Arithmetic overflow error", Qdomain_error); | |
2165 deferror (&Qunderflow_error, "underflow-error", | |
2166 "Arithmetic underflow error", Qdomain_error); | |
2167 } | |
2168 | |
2169 void | |
2170 syms_of_data (void) | |
2171 { | |
2172 defsymbol (&Qcons, "cons"); | |
2173 defsymbol (&Qkeyword, "keyword"); | |
2174 /* Qstring, Qinteger, Qsymbol, Qvector defined in general.c */ | |
2175 | |
2176 defsymbol (&Qquote, "quote"); | |
2177 defsymbol (&Qlambda, "lambda"); | |
2178 defsymbol (&Qsignal, "signal"); | |
2179 defsymbol (&Qtop_level, "top-level"); | |
2180 defsymbol (&Qignore, "ignore"); | |
2181 | |
2182 defsymbol (&Qlistp, "listp"); | |
2183 defsymbol (&Qconsp, "consp"); | |
2184 defsymbol (&Qsubrp, "subrp"); | |
2185 defsymbol (&Qsymbolp, "symbolp"); | |
2186 defsymbol (&Qkeywordp, "keywordp"); | |
2187 defsymbol (&Qintegerp, "integerp"); | |
2188 defsymbol (&Qcharacterp, "characterp"); | |
2189 defsymbol (&Qnatnump, "natnump"); | |
2190 defsymbol (&Qstringp, "stringp"); | |
2191 defsymbol (&Qarrayp, "arrayp"); | |
2192 defsymbol (&Qsequencep, "sequencep"); | |
2193 defsymbol (&Qbufferp, "bufferp"); | |
2194 defsymbol (&Qbitp, "bitp"); | |
2195 defsymbol (&Qbit_vectorp, "bit-vector-p"); | |
2196 defsymbol (&Qvectorp, "vectorp"); | |
2197 defsymbol (&Qcompiled_functionp, "compiled-function-p"); | |
2198 defsymbol (&Qchar_or_string_p, "char-or-string-p"); | |
2199 defsymbol (&Qmarkerp, "markerp"); | |
2200 defsymbol (&Qinteger_or_marker_p, "integer-or-marker-p"); | |
2201 /* HACK for 19.x only. */ | |
2202 defsymbol (&Qinteger_char_or_marker_p, "integer-or-marker-p"); | |
2203 | |
2204 #ifdef LISP_FLOAT_TYPE | |
2205 defsymbol (&Qfloatp, "floatp"); | |
2206 #endif /* LISP_FLOAT_TYPE */ | |
2207 defsymbol (&Qnumberp, "numberp"); | |
2208 defsymbol (&Qnumber_or_marker_p, "number-or-marker-p"); | |
2209 /* HACK for 19.x only. */ | |
2210 defsymbol (&Qnumber_char_or_marker_p, "number-or-marker-p"); | |
2211 | |
2212 defsymbol (&Qcdr, "cdr"); | |
2213 | |
2214 defsymbol (&Qweak_listp, "weak-list-p"); | |
2215 | |
2216 defsubr (&Swrong_type_argument); | |
2217 | |
2218 defsubr (&Seq); | |
2219 defsubr (&Snull); | |
2220 defsubr (&Slistp); | |
2221 defsubr (&Snlistp); | |
2222 defsubr (&Sconsp); | |
2223 defsubr (&Satom); | |
2224 defsubr (&Schar_or_string_p); | |
2225 defsubr (&Scharacterp); | |
2226 defsubr (&Sintegerp); | |
2227 defsubr (&Sinteger_or_marker_p); | |
2228 defsubr (&Snumberp); | |
2229 defsubr (&Snumber_or_marker_p); | |
2230 #ifdef LISP_FLOAT_TYPE | |
2231 defsubr (&Sfloatp); | |
2232 #endif /* LISP_FLOAT_TYPE */ | |
2233 defsubr (&Snatnump); | |
2234 defsubr (&Ssymbolp); | |
2235 defsubr (&Skeywordp); | |
2236 defsubr (&Sstringp); | |
2237 defsubr (&Svectorp); | |
2238 defsubr (&Sbitp); | |
2239 defsubr (&Sbit_vector_p); | |
2240 defsubr (&Sarrayp); | |
2241 defsubr (&Ssequencep); | |
2242 defsubr (&Smarkerp); | |
2243 defsubr (&Ssubrp); | |
2244 defsubr (&Ssubr_min_args); | |
2245 defsubr (&Ssubr_max_args); | |
2246 defsubr (&Scompiled_function_p); | |
2247 defsubr (&Stype_of); | |
2248 defsubr (&Scar); | |
2249 defsubr (&Scdr); | |
2250 defsubr (&Scar_safe); | |
2251 defsubr (&Scdr_safe); | |
2252 defsubr (&Ssetcar); | |
2253 defsubr (&Ssetcdr); | |
2254 defsubr (&Sindirect_function); | |
2255 defsubr (&Saref); | |
2256 defsubr (&Saset); | |
2257 | |
2258 defsubr (&Scompiled_function_instructions); | |
2259 defsubr (&Scompiled_function_constants); | |
2260 defsubr (&Scompiled_function_stack_depth); | |
2261 defsubr (&Scompiled_function_arglist); | |
2262 defsubr (&Scompiled_function_interactive); | |
2263 defsubr (&Scompiled_function_doc_string); | |
2264 defsubr (&Scompiled_function_domain); | |
2265 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | |
2266 defsubr (&Scompiled_function_annotation); | |
2267 #endif | |
2268 | |
2269 defsubr (&Snumber_to_string); | |
2270 defsubr (&Sstring_to_number); | |
2271 defsubr (&Seqlsign); | |
2272 defsubr (&Slss); | |
2273 defsubr (&Sgtr); | |
2274 defsubr (&Sleq); | |
2275 defsubr (&Sgeq); | |
2276 defsubr (&Sneq); | |
2277 defsubr (&Szerop); | |
2278 defsubr (&Splus); | |
2279 defsubr (&Sminus); | |
2280 defsubr (&Stimes); | |
2281 defsubr (&Squo); | |
2282 defsubr (&Srem); | |
2283 defsubr (&Smod); | |
2284 defsubr (&Smax); | |
2285 defsubr (&Smin); | |
2286 defsubr (&Slogand); | |
2287 defsubr (&Slogior); | |
2288 defsubr (&Slogxor); | |
2289 defsubr (&Slsh); | |
2290 defsubr (&Sash); | |
2291 defsubr (&Sadd1); | |
2292 defsubr (&Ssub1); | |
2293 defsubr (&Slognot); | |
2294 | |
2295 defsubr (&Sweak_list_p); | |
2296 defsubr (&Smake_weak_list); | |
2297 defsubr (&Sweak_list_type); | |
2298 defsubr (&Sweak_list_list); | |
2299 defsubr (&Sset_weak_list_list); | |
2300 } | |
2301 | |
2302 void | |
2303 vars_of_data (void) | |
2304 { | |
2305 /* This must not be staticpro'd */ | |
2306 Vall_weak_lists = Qnil; | |
2307 } |