Update copyright year.
[bpt/emacs.git] / src / fns.c
1 /* Random utility Lisp functions.
2 Copyright (C) 1985, 86, 87, 93, 94, 95, 97, 1998 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 2, 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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21
22 #include <config.h>
23
24 /* Note on some machines this defines `vector' as a typedef,
25 so make sure we don't use that name in this file. */
26 #undef vector
27 #define vector *****
28
29 #include "lisp.h"
30 #include "commands.h"
31 #include "charset.h"
32
33 #include "buffer.h"
34 #include "keyboard.h"
35 #include "intervals.h"
36 #include "frame.h"
37 #include "window.h"
38
39 #ifndef NULL
40 #define NULL (void *)0
41 #endif
42
43 #define DEFAULT_NONASCII_INSERT_OFFSET 0x800
44
45 /* Nonzero enables use of dialog boxes for questions
46 asked by mouse commands. */
47 int use_dialog_box;
48
49 extern Lisp_Object Flookup_key ();
50
51 extern int minibuffer_auto_raise;
52 extern Lisp_Object minibuf_window;
53
54 Lisp_Object Qstring_lessp, Qprovide, Qrequire;
55 Lisp_Object Qyes_or_no_p_history;
56 Lisp_Object Qcursor_in_echo_area;
57 Lisp_Object Qwidget_type;
58
59 static int internal_equal ();
60 \f
61 DEFUN ("identity", Fidentity, Sidentity, 1, 1, 0,
62 "Return the argument unchanged.")
63 (arg)
64 Lisp_Object arg;
65 {
66 return arg;
67 }
68
69 extern long get_random ();
70 extern void seed_random ();
71 extern long time ();
72
73 DEFUN ("random", Frandom, Srandom, 0, 1, 0,
74 "Return a pseudo-random number.\n\
75 All integers representable in Lisp are equally likely.\n\
76 On most systems, this is 28 bits' worth.\n\
77 With positive integer argument N, return random number in interval [0,N).\n\
78 With argument t, set the random number seed from the current time and pid.")
79 (n)
80 Lisp_Object n;
81 {
82 EMACS_INT val;
83 Lisp_Object lispy_val;
84 unsigned long denominator;
85
86 if (EQ (n, Qt))
87 seed_random (getpid () + time (NULL));
88 if (NATNUMP (n) && XFASTINT (n) != 0)
89 {
90 /* Try to take our random number from the higher bits of VAL,
91 not the lower, since (says Gentzel) the low bits of `random'
92 are less random than the higher ones. We do this by using the
93 quotient rather than the remainder. At the high end of the RNG
94 it's possible to get a quotient larger than n; discarding
95 these values eliminates the bias that would otherwise appear
96 when using a large n. */
97 denominator = ((unsigned long)1 << VALBITS) / XFASTINT (n);
98 do
99 val = get_random () / denominator;
100 while (val >= XFASTINT (n));
101 }
102 else
103 val = get_random ();
104 XSETINT (lispy_val, val);
105 return lispy_val;
106 }
107 \f
108 /* Random data-structure functions */
109
110 DEFUN ("length", Flength, Slength, 1, 1, 0,
111 "Return the length of vector, list or string SEQUENCE.\n\
112 A byte-code function object is also allowed.\n\
113 If the string contains multibyte characters, this is not the necessarily\n\
114 the number of characters in the string; it is the number of bytes.\n\
115 To get the number of characters, use `chars-in-string'")
116 (sequence)
117 register Lisp_Object sequence;
118 {
119 register Lisp_Object tail, val;
120 register int i;
121
122 retry:
123 if (STRINGP (sequence))
124 XSETFASTINT (val, XSTRING (sequence)->size);
125 else if (VECTORP (sequence))
126 XSETFASTINT (val, XVECTOR (sequence)->size);
127 else if (CHAR_TABLE_P (sequence))
128 XSETFASTINT (val, CHAR_TABLE_ORDINARY_SLOTS);
129 else if (BOOL_VECTOR_P (sequence))
130 XSETFASTINT (val, XBOOL_VECTOR (sequence)->size);
131 else if (COMPILEDP (sequence))
132 XSETFASTINT (val, XVECTOR (sequence)->size & PSEUDOVECTOR_SIZE_MASK);
133 else if (CONSP (sequence))
134 {
135 for (i = 0, tail = sequence; !NILP (tail); i++)
136 {
137 QUIT;
138 tail = Fcdr (tail);
139 }
140
141 XSETFASTINT (val, i);
142 }
143 else if (NILP (sequence))
144 XSETFASTINT (val, 0);
145 else
146 {
147 sequence = wrong_type_argument (Qsequencep, sequence);
148 goto retry;
149 }
150 return val;
151 }
152
153 /* This does not check for quits. That is safe
154 since it must terminate. */
155
156 DEFUN ("safe-length", Fsafe_length, Ssafe_length, 1, 1, 0,
157 "Return the length of a list, but avoid error or infinite loop.\n\
158 This function never gets an error. If LIST is not really a list,\n\
159 it returns 0. If LIST is circular, it returns a finite value\n\
160 which is at least the number of distinct elements.")
161 (list)
162 Lisp_Object list;
163 {
164 Lisp_Object tail, halftail, length;
165 int len = 0;
166
167 /* halftail is used to detect circular lists. */
168 halftail = list;
169 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
170 {
171 if (EQ (tail, halftail) && len != 0)
172 break;
173 len++;
174 if ((len & 1) == 0)
175 halftail = XCONS (halftail)->cdr;
176 }
177
178 XSETINT (length, len);
179 return length;
180 }
181
182 DEFUN ("string-equal", Fstring_equal, Sstring_equal, 2, 2, 0,
183 "Return t if two strings have identical contents.\n\
184 Case is significant, but text properties are ignored.\n\
185 Symbols are also allowed; their print names are used instead.")
186 (s1, s2)
187 register Lisp_Object s1, s2;
188 {
189 if (SYMBOLP (s1))
190 XSETSTRING (s1, XSYMBOL (s1)->name);
191 if (SYMBOLP (s2))
192 XSETSTRING (s2, XSYMBOL (s2)->name);
193 CHECK_STRING (s1, 0);
194 CHECK_STRING (s2, 1);
195
196 if (XSTRING (s1)->size != XSTRING (s2)->size
197 || XSTRING (s1)->size_byte != XSTRING (s2)->size_byte
198 || bcmp (XSTRING (s1)->data, XSTRING (s2)->data, XSTRING (s1)->size_byte))
199 return Qnil;
200 return Qt;
201 }
202
203 DEFUN ("string-lessp", Fstring_lessp, Sstring_lessp, 2, 2, 0,
204 "Return t if first arg string is less than second in lexicographic order.\n\
205 Case is significant.\n\
206 Symbols are also allowed; their print names are used instead.")
207 (s1, s2)
208 register Lisp_Object s1, s2;
209 {
210 register int end;
211 register int i1, i1_byte, i2, i2_byte;
212
213 if (SYMBOLP (s1))
214 XSETSTRING (s1, XSYMBOL (s1)->name);
215 if (SYMBOLP (s2))
216 XSETSTRING (s2, XSYMBOL (s2)->name);
217 CHECK_STRING (s1, 0);
218 CHECK_STRING (s2, 1);
219
220 i1 = i1_byte = i2 = i2_byte = 0;
221
222 end = XSTRING (s1)->size;
223 if (end > XSTRING (s2)->size)
224 end = XSTRING (s2)->size;
225
226 while (i1 < end)
227 {
228 /* When we find a mismatch, we must compare the
229 characters, not just the bytes. */
230 int c1, c2;
231
232 if (STRING_MULTIBYTE (s1))
233 FETCH_STRING_CHAR_ADVANCE (c1, s1, i1, i1_byte);
234 else
235 c1 = XSTRING (s1)->data[i1++];
236
237 if (STRING_MULTIBYTE (s2))
238 FETCH_STRING_CHAR_ADVANCE (c2, s2, i2, i2_byte);
239 else
240 c2 = XSTRING (s2)->data[i2++];
241
242 if (c1 != c2)
243 return c1 < c2 ? Qt : Qnil;
244 }
245 return i1 < XSTRING (s2)->size ? Qt : Qnil;
246 }
247 \f
248 static Lisp_Object concat ();
249
250 /* ARGSUSED */
251 Lisp_Object
252 concat2 (s1, s2)
253 Lisp_Object s1, s2;
254 {
255 #ifdef NO_ARG_ARRAY
256 Lisp_Object args[2];
257 args[0] = s1;
258 args[1] = s2;
259 return concat (2, args, Lisp_String, 0);
260 #else
261 return concat (2, &s1, Lisp_String, 0);
262 #endif /* NO_ARG_ARRAY */
263 }
264
265 /* ARGSUSED */
266 Lisp_Object
267 concat3 (s1, s2, s3)
268 Lisp_Object s1, s2, s3;
269 {
270 #ifdef NO_ARG_ARRAY
271 Lisp_Object args[3];
272 args[0] = s1;
273 args[1] = s2;
274 args[2] = s3;
275 return concat (3, args, Lisp_String, 0);
276 #else
277 return concat (3, &s1, Lisp_String, 0);
278 #endif /* NO_ARG_ARRAY */
279 }
280
281 DEFUN ("append", Fappend, Sappend, 0, MANY, 0,
282 "Concatenate all the arguments and make the result a list.\n\
283 The result is a list whose elements are the elements of all the arguments.\n\
284 Each argument may be a list, vector or string.\n\
285 The last argument is not copied, just used as the tail of the new list.")
286 (nargs, args)
287 int nargs;
288 Lisp_Object *args;
289 {
290 return concat (nargs, args, Lisp_Cons, 1);
291 }
292
293 DEFUN ("concat", Fconcat, Sconcat, 0, MANY, 0,
294 "Concatenate all the arguments and make the result a string.\n\
295 The result is a string whose elements are the elements of all the arguments.\n\
296 Each argument may be a string or a list or vector of characters (integers).\n\
297 \n\
298 Do not use individual integers as arguments!\n\
299 The behavior of `concat' in that case will be changed later!\n\
300 If your program passes an integer as an argument to `concat',\n\
301 you should change it right away not to do so.")
302 (nargs, args)
303 int nargs;
304 Lisp_Object *args;
305 {
306 return concat (nargs, args, Lisp_String, 0);
307 }
308
309 DEFUN ("vconcat", Fvconcat, Svconcat, 0, MANY, 0,
310 "Concatenate all the arguments and make the result a vector.\n\
311 The result is a vector whose elements are the elements of all the arguments.\n\
312 Each argument may be a list, vector or string.")
313 (nargs, args)
314 int nargs;
315 Lisp_Object *args;
316 {
317 return concat (nargs, args, Lisp_Vectorlike, 0);
318 }
319
320 /* Retrun a copy of a sub char table ARG. The elements except for a
321 nested sub char table are not copied. */
322 static Lisp_Object
323 copy_sub_char_table (arg)
324 Lisp_Object arg;
325 {
326 Lisp_Object copy = make_sub_char_table (XCHAR_TABLE (arg)->defalt);
327 int i;
328
329 /* Copy all the contents. */
330 bcopy (XCHAR_TABLE (arg)->contents, XCHAR_TABLE (copy)->contents,
331 SUB_CHAR_TABLE_ORDINARY_SLOTS * sizeof (Lisp_Object));
332 /* Recursively copy any sub char-tables in the ordinary slots. */
333 for (i = 32; i < SUB_CHAR_TABLE_ORDINARY_SLOTS; i++)
334 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
335 XCHAR_TABLE (copy)->contents[i]
336 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
337
338 return copy;
339 }
340
341
342 DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
343 "Return a copy of a list, vector or string.\n\
344 The elements of a list or vector are not copied; they are shared\n\
345 with the original.")
346 (arg)
347 Lisp_Object arg;
348 {
349 if (NILP (arg)) return arg;
350
351 if (CHAR_TABLE_P (arg))
352 {
353 int i;
354 Lisp_Object copy;
355
356 copy = Fmake_char_table (XCHAR_TABLE (arg)->purpose, Qnil);
357 /* Copy all the slots, including the extra ones. */
358 bcopy (XVECTOR (arg)->contents, XVECTOR (copy)->contents,
359 ((XCHAR_TABLE (arg)->size & PSEUDOVECTOR_SIZE_MASK)
360 * sizeof (Lisp_Object)));
361
362 /* Recursively copy any sub char tables in the ordinary slots
363 for multibyte characters. */
364 for (i = CHAR_TABLE_SINGLE_BYTE_SLOTS;
365 i < CHAR_TABLE_ORDINARY_SLOTS; i++)
366 if (SUB_CHAR_TABLE_P (XCHAR_TABLE (arg)->contents[i]))
367 XCHAR_TABLE (copy)->contents[i]
368 = copy_sub_char_table (XCHAR_TABLE (copy)->contents[i]);
369
370 return copy;
371 }
372
373 if (BOOL_VECTOR_P (arg))
374 {
375 Lisp_Object val;
376 int size_in_chars
377 = (XBOOL_VECTOR (arg)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
378
379 val = Fmake_bool_vector (Flength (arg), Qnil);
380 bcopy (XBOOL_VECTOR (arg)->data, XBOOL_VECTOR (val)->data,
381 size_in_chars);
382 return val;
383 }
384
385 if (!CONSP (arg) && !VECTORP (arg) && !STRINGP (arg))
386 arg = wrong_type_argument (Qsequencep, arg);
387 return concat (1, &arg, CONSP (arg) ? Lisp_Cons : XTYPE (arg), 0);
388 }
389
390 static Lisp_Object
391 concat (nargs, args, target_type, last_special)
392 int nargs;
393 Lisp_Object *args;
394 enum Lisp_Type target_type;
395 int last_special;
396 {
397 Lisp_Object val;
398 register Lisp_Object tail;
399 register Lisp_Object this;
400 int toindex;
401 int toindex_byte;
402 register int result_len;
403 register int result_len_byte;
404 register int argnum;
405 Lisp_Object last_tail;
406 Lisp_Object prev;
407 int some_multibyte;
408
409 /* In append, the last arg isn't treated like the others */
410 if (last_special && nargs > 0)
411 {
412 nargs--;
413 last_tail = args[nargs];
414 }
415 else
416 last_tail = Qnil;
417
418 /* Canonicalize each argument. */
419 for (argnum = 0; argnum < nargs; argnum++)
420 {
421 this = args[argnum];
422 if (!(CONSP (this) || NILP (this) || VECTORP (this) || STRINGP (this)
423 || COMPILEDP (this) || BOOL_VECTOR_P (this)))
424 {
425 if (INTEGERP (this))
426 args[argnum] = Fnumber_to_string (this);
427 else
428 args[argnum] = wrong_type_argument (Qsequencep, this);
429 }
430 }
431
432 /* Compute total length in chars of arguments in RESULT_LEN.
433 If desired output is a string, also compute length in bytes
434 in RESULT_LEN_BYTE, and determine in SOME_MULTIBYTE
435 whether the result should be a multibyte string. */
436 result_len_byte = 0;
437 result_len = 0;
438 some_multibyte = 0;
439 for (argnum = 0; argnum < nargs; argnum++)
440 {
441 int len;
442 this = args[argnum];
443 len = XFASTINT (Flength (this));
444 if (target_type == Lisp_String)
445 {
446 /* We must count the number of bytes needed in the string
447 as well as the number of characters. */
448 int i;
449 Lisp_Object ch;
450 int this_len_byte;
451
452 if (VECTORP (this))
453 for (i = 0; i < len; i++)
454 {
455 ch = XVECTOR (this)->contents[i];
456 if (! INTEGERP (ch))
457 wrong_type_argument (Qintegerp, ch);
458 this_len_byte = XFASTINT (Fchar_bytes (ch));
459 result_len_byte += this_len_byte;
460 if (this_len_byte > 1)
461 some_multibyte = 1;
462 }
463 else if (CONSP (this))
464 for (; CONSP (this); this = XCONS (this)->cdr)
465 {
466 ch = XCONS (this)->car;
467 if (! INTEGERP (ch))
468 wrong_type_argument (Qintegerp, ch);
469 this_len_byte = XFASTINT (Fchar_bytes (ch));
470 result_len_byte += this_len_byte;
471 if (this_len_byte > 1)
472 some_multibyte = 1;
473 }
474 else if (STRINGP (this))
475 {
476 if (STRING_MULTIBYTE (this))
477 {
478 some_multibyte = 1;
479 result_len_byte += XSTRING (this)->size_byte;
480 }
481 else
482 result_len_byte += count_size_as_multibyte (XSTRING (this)->data,
483 XSTRING (this)->size);
484 }
485 }
486
487 result_len += len;
488 }
489
490 if (! some_multibyte)
491 result_len_byte = result_len;
492
493 /* Create the output object. */
494 if (target_type == Lisp_Cons)
495 val = Fmake_list (make_number (result_len), Qnil);
496 else if (target_type == Lisp_Vectorlike)
497 val = Fmake_vector (make_number (result_len), Qnil);
498 else
499 val = make_uninit_multibyte_string (result_len, result_len_byte);
500
501 /* In `append', if all but last arg are nil, return last arg. */
502 if (target_type == Lisp_Cons && EQ (val, Qnil))
503 return last_tail;
504
505 /* Copy the contents of the args into the result. */
506 if (CONSP (val))
507 tail = val, toindex = -1; /* -1 in toindex is flag we are making a list */
508 else
509 toindex = 0, toindex_byte = 0;
510
511 prev = Qnil;
512
513 for (argnum = 0; argnum < nargs; argnum++)
514 {
515 Lisp_Object thislen;
516 int thisleni;
517 register unsigned int thisindex = 0;
518 register unsigned int thisindex_byte = 0;
519
520 this = args[argnum];
521 if (!CONSP (this))
522 thislen = Flength (this), thisleni = XINT (thislen);
523
524 if (STRINGP (this) && STRINGP (val)
525 && ! NULL_INTERVAL_P (XSTRING (this)->intervals))
526 copy_text_properties (make_number (0), thislen, this,
527 make_number (toindex), val, Qnil);
528
529 /* Between strings of the same kind, copy fast. */
530 if (STRINGP (this) && STRINGP (val)
531 && STRING_MULTIBYTE (this) == some_multibyte)
532 {
533 int thislen_byte = XSTRING (this)->size_byte;
534 bcopy (XSTRING (this)->data, XSTRING (val)->data + toindex_byte,
535 XSTRING (this)->size_byte);
536 toindex_byte += thislen_byte;
537 toindex += thisleni;
538 }
539 /* Copy a single-byte string to a multibyte string. */
540 else if (STRINGP (this) && STRINGP (val))
541 {
542 toindex_byte += copy_text (XSTRING (this)->data,
543 XSTRING (val)->data + toindex_byte,
544 XSTRING (this)->size, 0, 1);
545 toindex += thisleni;
546 }
547 else
548 /* Copy element by element. */
549 while (1)
550 {
551 register Lisp_Object elt;
552
553 /* Fetch next element of `this' arg into `elt', or break if
554 `this' is exhausted. */
555 if (NILP (this)) break;
556 if (CONSP (this))
557 elt = XCONS (this)->car, this = XCONS (this)->cdr;
558 else
559 {
560 if (thisindex >= thisleni) break;
561 if (STRINGP (this))
562 {
563 if (STRING_MULTIBYTE (this))
564 {
565 int c;
566 FETCH_STRING_CHAR_ADVANCE (c, this,
567 thisindex,
568 thisindex_byte);
569 XSETFASTINT (elt, c);
570 }
571 else
572 {
573 unsigned char c;
574 XSETFASTINT (elt, XSTRING (this)->data[thisindex++]);
575 if (some_multibyte)
576 XSETINT (elt,
577 unibyte_char_to_multibyte (XINT (elt)));
578 }
579 }
580 else if (BOOL_VECTOR_P (this))
581 {
582 int size_in_chars
583 = ((XBOOL_VECTOR (this)->size + BITS_PER_CHAR - 1)
584 / BITS_PER_CHAR);
585 int byte;
586 byte = XBOOL_VECTOR (val)->data[thisindex / BITS_PER_CHAR];
587 if (byte & (1 << (thisindex % BITS_PER_CHAR)))
588 elt = Qt;
589 else
590 elt = Qnil;
591 }
592 else
593 elt = XVECTOR (this)->contents[thisindex++];
594 }
595
596 /* Store this element into the result. */
597 if (toindex < 0)
598 {
599 XCONS (tail)->car = elt;
600 prev = tail;
601 tail = XCONS (tail)->cdr;
602 }
603 else if (VECTORP (val))
604 XVECTOR (val)->contents[toindex++] = elt;
605 else
606 {
607 CHECK_NUMBER (elt, 0);
608 if (SINGLE_BYTE_CHAR_P (XINT (elt)))
609 {
610 XSTRING (val)->data[toindex++] = XINT (elt);
611 toindex_byte++;
612 }
613 else
614 /* If we have any multibyte characters,
615 we already decided to make a multibyte string. */
616 {
617 int c = XINT (elt);
618 unsigned char work[4], *str;
619 int i = CHAR_STRING (c, work, str);
620
621 /* P exists as a variable
622 to avoid a bug on the Masscomp C compiler. */
623 unsigned char *p = & XSTRING (val)->data[toindex_byte];
624 bcopy (str, p, i);
625 toindex_byte += i;
626 toindex++;
627 }
628 }
629 }
630 }
631 if (!NILP (prev))
632 XCONS (prev)->cdr = last_tail;
633
634 return val;
635 }
636 \f
637 static Lisp_Object string_char_byte_cache_string;
638 static int string_char_byte_cache_charpos;
639 static int string_char_byte_cache_bytepos;
640
641 /* Return the character index corresponding to CHAR_INDEX in STRING. */
642
643 int
644 string_char_to_byte (string, char_index)
645 Lisp_Object string;
646 int char_index;
647 {
648 int i, i_byte;
649 int best_below, best_below_byte;
650 int best_above, best_above_byte;
651
652 if (! STRING_MULTIBYTE (string))
653 return char_index;
654
655 best_below = best_below_byte = 0;
656 best_above = XSTRING (string)->size;
657 best_above_byte = XSTRING (string)->size_byte;
658
659 if (EQ (string, string_char_byte_cache_string))
660 {
661 if (string_char_byte_cache_charpos < char_index)
662 {
663 best_below = string_char_byte_cache_charpos;
664 best_below_byte = string_char_byte_cache_bytepos;
665 }
666 else
667 {
668 best_above = string_char_byte_cache_charpos;
669 best_above_byte = string_char_byte_cache_bytepos;
670 }
671 }
672
673 if (char_index - best_below < best_above - char_index)
674 {
675 while (best_below < char_index)
676 {
677 int c;
678 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
679 }
680 i = best_below;
681 i_byte = best_below_byte;
682 }
683 else
684 {
685 while (best_above > char_index)
686 {
687 int best_above_byte_saved = --best_above_byte;
688
689 while (best_above_byte > 0
690 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
691 best_above_byte--;
692 if (XSTRING (string)->data[best_above_byte] < 0x80)
693 best_above_byte = best_above_byte_saved;
694 best_above--;
695 }
696 i = best_above;
697 i_byte = best_above_byte;
698 }
699
700 string_char_byte_cache_bytepos = i_byte;
701 string_char_byte_cache_charpos = i;
702 string_char_byte_cache_string = string;
703
704 return i_byte;
705 }
706 \f
707 /* Return the character index corresponding to BYTE_INDEX in STRING. */
708
709 int
710 string_byte_to_char (string, byte_index)
711 Lisp_Object string;
712 int byte_index;
713 {
714 int i, i_byte;
715 int best_below, best_below_byte;
716 int best_above, best_above_byte;
717
718 if (! STRING_MULTIBYTE (string))
719 return byte_index;
720
721 best_below = best_below_byte = 0;
722 best_above = XSTRING (string)->size;
723 best_above_byte = XSTRING (string)->size_byte;
724
725 if (EQ (string, string_char_byte_cache_string))
726 {
727 if (string_char_byte_cache_bytepos < byte_index)
728 {
729 best_below = string_char_byte_cache_charpos;
730 best_below_byte = string_char_byte_cache_bytepos;
731 }
732 else
733 {
734 best_above = string_char_byte_cache_charpos;
735 best_above_byte = string_char_byte_cache_bytepos;
736 }
737 }
738
739 if (byte_index - best_below_byte < best_above_byte - byte_index)
740 {
741 while (best_below_byte < byte_index)
742 {
743 int c;
744 FETCH_STRING_CHAR_ADVANCE (c, string, best_below, best_below_byte);
745 }
746 i = best_below;
747 i_byte = best_below_byte;
748 }
749 else
750 {
751 while (best_above_byte > byte_index)
752 {
753 int best_above_byte_saved = --best_above_byte;
754
755 while (best_above_byte > 0
756 && !CHAR_HEAD_P (XSTRING (string)->data[best_above_byte]))
757 best_above_byte--;
758 if (XSTRING (string)->data[best_above_byte] < 0x80)
759 best_above_byte = best_above_byte_saved;
760 best_above--;
761 }
762 i = best_above;
763 i_byte = best_above_byte;
764 }
765
766 string_char_byte_cache_bytepos = i_byte;
767 string_char_byte_cache_charpos = i;
768 string_char_byte_cache_string = string;
769
770 return i;
771 }
772 \f
773 /* Convert STRING to a multibyte string.
774 Single-byte characters 0200 through 0377 are converted
775 by adding nonascii_insert_offset to each. */
776
777 Lisp_Object
778 string_make_multibyte (string)
779 Lisp_Object string;
780 {
781 unsigned char *buf;
782 int nbytes;
783
784 if (STRING_MULTIBYTE (string))
785 return string;
786
787 nbytes = count_size_as_multibyte (XSTRING (string)->data,
788 XSTRING (string)->size);
789 buf = (unsigned char *) alloca (nbytes);
790 copy_text (XSTRING (string)->data, buf, XSTRING (string)->size_byte,
791 0, 1);
792
793 return make_multibyte_string (buf, XSTRING (string)->size, nbytes);
794 }
795
796 /* Convert STRING to a single-byte string. */
797
798 Lisp_Object
799 string_make_unibyte (string)
800 Lisp_Object string;
801 {
802 unsigned char *buf;
803
804 if (! STRING_MULTIBYTE (string))
805 return string;
806
807 buf = (unsigned char *) alloca (XSTRING (string)->size);
808
809 copy_text (XSTRING (string)->data, buf, XSTRING (string)->size_byte,
810 1, 0);
811
812 return make_unibyte_string (buf, XSTRING (string)->size);
813 }
814
815 DEFUN ("string-make-multibyte", Fstring_make_multibyte, Sstring_make_multibyte,
816 1, 1, 0,
817 "Return the multibyte equivalent of STRING.")
818 (string)
819 Lisp_Object string;
820 {
821 return string_make_multibyte (string);
822 }
823
824 DEFUN ("string-make-unibyte", Fstring_make_unibyte, Sstring_make_unibyte,
825 1, 1, 0,
826 "Return the unibyte equivalent of STRING.")
827 (string)
828 Lisp_Object string;
829 {
830 return string_make_unibyte (string);
831 }
832 \f
833 DEFUN ("copy-alist", Fcopy_alist, Scopy_alist, 1, 1, 0,
834 "Return a copy of ALIST.\n\
835 This is an alist which represents the same mapping from objects to objects,\n\
836 but does not share the alist structure with ALIST.\n\
837 The objects mapped (cars and cdrs of elements of the alist)\n\
838 are shared, however.\n\
839 Elements of ALIST that are not conses are also shared.")
840 (alist)
841 Lisp_Object alist;
842 {
843 register Lisp_Object tem;
844
845 CHECK_LIST (alist, 0);
846 if (NILP (alist))
847 return alist;
848 alist = concat (1, &alist, Lisp_Cons, 0);
849 for (tem = alist; CONSP (tem); tem = XCONS (tem)->cdr)
850 {
851 register Lisp_Object car;
852 car = XCONS (tem)->car;
853
854 if (CONSP (car))
855 XCONS (tem)->car = Fcons (XCONS (car)->car, XCONS (car)->cdr);
856 }
857 return alist;
858 }
859
860 DEFUN ("substring", Fsubstring, Ssubstring, 2, 3, 0,
861 "Return a substring of STRING, starting at index FROM and ending before TO.\n\
862 TO may be nil or omitted; then the substring runs to the end of STRING.\n\
863 If FROM or TO is negative, it counts from the end.\n\
864 \n\
865 This function allows vectors as well as strings.")
866 (string, from, to)
867 Lisp_Object string;
868 register Lisp_Object from, to;
869 {
870 Lisp_Object res;
871 int size;
872 int size_byte;
873 int from_char, to_char;
874 int from_byte, to_byte;
875
876 if (! (STRINGP (string) || VECTORP (string)))
877 wrong_type_argument (Qarrayp, string);
878
879 CHECK_NUMBER (from, 1);
880
881 if (STRINGP (string))
882 {
883 size = XSTRING (string)->size;
884 size_byte = XSTRING (string)->size_byte;
885 }
886 else
887 size = XVECTOR (string)->size;
888
889 if (NILP (to))
890 {
891 to_char = size;
892 to_byte = size_byte;
893 }
894 else
895 {
896 CHECK_NUMBER (to, 2);
897
898 to_char = XINT (to);
899 if (to_char < 0)
900 to_char += size;
901
902 if (STRINGP (string))
903 to_byte = string_char_to_byte (string, to_char);
904 }
905
906 from_char = XINT (from);
907 if (from_char < 0)
908 from_char += size;
909 if (STRINGP (string))
910 from_byte = string_char_to_byte (string, from_char);
911
912 if (!(0 <= from_char && from_char <= to_char && to_char <= size))
913 args_out_of_range_3 (string, make_number (from_char),
914 make_number (to_char));
915
916 if (STRINGP (string))
917 {
918 res = make_multibyte_string (XSTRING (string)->data + from_byte,
919 to_char - from_char, to_byte - from_byte);
920 copy_text_properties (from_char, to_char, string,
921 make_number (0), res, Qnil);
922 }
923 else
924 res = Fvector (to_char - from_char,
925 XVECTOR (string)->contents + from_char);
926
927 return res;
928 }
929
930 /* Extract a substring of STRING, giving start and end positions
931 both in characters and in bytes. */
932
933 Lisp_Object
934 substring_both (string, from, from_byte, to, to_byte)
935 Lisp_Object string;
936 int from, from_byte, to, to_byte;
937 {
938 Lisp_Object res;
939 int size;
940 int size_byte;
941
942 if (! (STRINGP (string) || VECTORP (string)))
943 wrong_type_argument (Qarrayp, string);
944
945 if (STRINGP (string))
946 {
947 size = XSTRING (string)->size;
948 size_byte = XSTRING (string)->size_byte;
949 }
950 else
951 size = XVECTOR (string)->size;
952
953 if (!(0 <= from && from <= to && to <= size))
954 args_out_of_range_3 (string, make_number (from), make_number (to));
955
956 if (STRINGP (string))
957 {
958 res = make_multibyte_string (XSTRING (string)->data + from_byte,
959 to - from, to_byte - from_byte);
960 copy_text_properties (from, to, string, make_number (0), res, Qnil);
961 }
962 else
963 res = Fvector (to - from,
964 XVECTOR (string)->contents + from);
965
966 return res;
967 }
968 \f
969 DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
970 "Take cdr N times on LIST, returns the result.")
971 (n, list)
972 Lisp_Object n;
973 register Lisp_Object list;
974 {
975 register int i, num;
976 CHECK_NUMBER (n, 0);
977 num = XINT (n);
978 for (i = 0; i < num && !NILP (list); i++)
979 {
980 QUIT;
981 list = Fcdr (list);
982 }
983 return list;
984 }
985
986 DEFUN ("nth", Fnth, Snth, 2, 2, 0,
987 "Return the Nth element of LIST.\n\
988 N counts from zero. If LIST is not that long, nil is returned.")
989 (n, list)
990 Lisp_Object n, list;
991 {
992 return Fcar (Fnthcdr (n, list));
993 }
994
995 DEFUN ("elt", Felt, Selt, 2, 2, 0,
996 "Return element of SEQUENCE at index N.")
997 (sequence, n)
998 register Lisp_Object sequence, n;
999 {
1000 CHECK_NUMBER (n, 0);
1001 while (1)
1002 {
1003 if (CONSP (sequence) || NILP (sequence))
1004 return Fcar (Fnthcdr (n, sequence));
1005 else if (STRINGP (sequence) || VECTORP (sequence)
1006 || BOOL_VECTOR_P (sequence) || CHAR_TABLE_P (sequence))
1007 return Faref (sequence, n);
1008 else
1009 sequence = wrong_type_argument (Qsequencep, sequence);
1010 }
1011 }
1012
1013 DEFUN ("member", Fmember, Smember, 2, 2, 0,
1014 "Return non-nil if ELT is an element of LIST. Comparison done with `equal'.\n\
1015 The value is actually the tail of LIST whose car is ELT.")
1016 (elt, list)
1017 register Lisp_Object elt;
1018 Lisp_Object list;
1019 {
1020 register Lisp_Object tail;
1021 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1022 {
1023 register Lisp_Object tem;
1024 tem = Fcar (tail);
1025 if (! NILP (Fequal (elt, tem)))
1026 return tail;
1027 QUIT;
1028 }
1029 return Qnil;
1030 }
1031
1032 DEFUN ("memq", Fmemq, Smemq, 2, 2, 0,
1033 "Return non-nil if ELT is an element of LIST. Comparison done with EQ.\n\
1034 The value is actually the tail of LIST whose car is ELT.")
1035 (elt, list)
1036 register Lisp_Object elt;
1037 Lisp_Object list;
1038 {
1039 register Lisp_Object tail;
1040 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1041 {
1042 register Lisp_Object tem;
1043 tem = Fcar (tail);
1044 if (EQ (elt, tem)) return tail;
1045 QUIT;
1046 }
1047 return Qnil;
1048 }
1049
1050 DEFUN ("assq", Fassq, Sassq, 2, 2, 0,
1051 "Return non-nil if KEY is `eq' to the car of an element of LIST.\n\
1052 The value is actually the element of LIST whose car is KEY.\n\
1053 Elements of LIST that are not conses are ignored.")
1054 (key, list)
1055 register Lisp_Object key;
1056 Lisp_Object list;
1057 {
1058 register Lisp_Object tail;
1059 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1060 {
1061 register Lisp_Object elt, tem;
1062 elt = Fcar (tail);
1063 if (!CONSP (elt)) continue;
1064 tem = XCONS (elt)->car;
1065 if (EQ (key, tem)) return elt;
1066 QUIT;
1067 }
1068 return Qnil;
1069 }
1070
1071 /* Like Fassq but never report an error and do not allow quits.
1072 Use only on lists known never to be circular. */
1073
1074 Lisp_Object
1075 assq_no_quit (key, list)
1076 register Lisp_Object key;
1077 Lisp_Object list;
1078 {
1079 register Lisp_Object tail;
1080 for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
1081 {
1082 register Lisp_Object elt, tem;
1083 elt = Fcar (tail);
1084 if (!CONSP (elt)) continue;
1085 tem = XCONS (elt)->car;
1086 if (EQ (key, tem)) return elt;
1087 }
1088 return Qnil;
1089 }
1090
1091 DEFUN ("assoc", Fassoc, Sassoc, 2, 2, 0,
1092 "Return non-nil if KEY is `equal' to the car of an element of LIST.\n\
1093 The value is actually the element of LIST whose car equals KEY.")
1094 (key, list)
1095 register Lisp_Object key;
1096 Lisp_Object list;
1097 {
1098 register Lisp_Object tail;
1099 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1100 {
1101 register Lisp_Object elt, tem;
1102 elt = Fcar (tail);
1103 if (!CONSP (elt)) continue;
1104 tem = Fequal (XCONS (elt)->car, key);
1105 if (!NILP (tem)) return elt;
1106 QUIT;
1107 }
1108 return Qnil;
1109 }
1110
1111 DEFUN ("rassq", Frassq, Srassq, 2, 2, 0,
1112 "Return non-nil if ELT is `eq' to the cdr of an element of LIST.\n\
1113 The value is actually the element of LIST whose cdr is ELT.")
1114 (key, list)
1115 register Lisp_Object key;
1116 Lisp_Object list;
1117 {
1118 register Lisp_Object tail;
1119 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1120 {
1121 register Lisp_Object elt, tem;
1122 elt = Fcar (tail);
1123 if (!CONSP (elt)) continue;
1124 tem = XCONS (elt)->cdr;
1125 if (EQ (key, tem)) return elt;
1126 QUIT;
1127 }
1128 return Qnil;
1129 }
1130
1131 DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
1132 "Return non-nil if KEY is `equal' to the cdr of an element of LIST.\n\
1133 The value is actually the element of LIST whose cdr equals KEY.")
1134 (key, list)
1135 register Lisp_Object key;
1136 Lisp_Object list;
1137 {
1138 register Lisp_Object tail;
1139 for (tail = list; !NILP (tail); tail = XCONS (tail)->cdr)
1140 {
1141 register Lisp_Object elt, tem;
1142 elt = Fcar (tail);
1143 if (!CONSP (elt)) continue;
1144 tem = Fequal (XCONS (elt)->cdr, key);
1145 if (!NILP (tem)) return elt;
1146 QUIT;
1147 }
1148 return Qnil;
1149 }
1150 \f
1151 DEFUN ("delq", Fdelq, Sdelq, 2, 2, 0,
1152 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1153 The modified LIST is returned. Comparison is done with `eq'.\n\
1154 If the first member of LIST is ELT, there is no way to remove it by side effect;\n\
1155 therefore, write `(setq foo (delq element foo))'\n\
1156 to be sure of changing the value of `foo'.")
1157 (elt, list)
1158 register Lisp_Object elt;
1159 Lisp_Object list;
1160 {
1161 register Lisp_Object tail, prev;
1162 register Lisp_Object tem;
1163
1164 tail = list;
1165 prev = Qnil;
1166 while (!NILP (tail))
1167 {
1168 tem = Fcar (tail);
1169 if (EQ (elt, tem))
1170 {
1171 if (NILP (prev))
1172 list = XCONS (tail)->cdr;
1173 else
1174 Fsetcdr (prev, XCONS (tail)->cdr);
1175 }
1176 else
1177 prev = tail;
1178 tail = XCONS (tail)->cdr;
1179 QUIT;
1180 }
1181 return list;
1182 }
1183
1184 DEFUN ("delete", Fdelete, Sdelete, 2, 2, 0,
1185 "Delete by side effect any occurrences of ELT as a member of LIST.\n\
1186 The modified LIST is returned. Comparison is done with `equal'.\n\
1187 If the first member of LIST is ELT, deleting it is not a side effect;\n\
1188 it is simply using a different list.\n\
1189 Therefore, write `(setq foo (delete element foo))'\n\
1190 to be sure of changing the value of `foo'.")
1191 (elt, list)
1192 register Lisp_Object elt;
1193 Lisp_Object list;
1194 {
1195 register Lisp_Object tail, prev;
1196 register Lisp_Object tem;
1197
1198 tail = list;
1199 prev = Qnil;
1200 while (!NILP (tail))
1201 {
1202 tem = Fcar (tail);
1203 if (! NILP (Fequal (elt, tem)))
1204 {
1205 if (NILP (prev))
1206 list = XCONS (tail)->cdr;
1207 else
1208 Fsetcdr (prev, XCONS (tail)->cdr);
1209 }
1210 else
1211 prev = tail;
1212 tail = XCONS (tail)->cdr;
1213 QUIT;
1214 }
1215 return list;
1216 }
1217
1218 DEFUN ("nreverse", Fnreverse, Snreverse, 1, 1, 0,
1219 "Reverse LIST by modifying cdr pointers.\n\
1220 Returns the beginning of the reversed list.")
1221 (list)
1222 Lisp_Object list;
1223 {
1224 register Lisp_Object prev, tail, next;
1225
1226 if (NILP (list)) return list;
1227 prev = Qnil;
1228 tail = list;
1229 while (!NILP (tail))
1230 {
1231 QUIT;
1232 next = Fcdr (tail);
1233 Fsetcdr (tail, prev);
1234 prev = tail;
1235 tail = next;
1236 }
1237 return prev;
1238 }
1239
1240 DEFUN ("reverse", Freverse, Sreverse, 1, 1, 0,
1241 "Reverse LIST, copying. Returns the beginning of the reversed list.\n\
1242 See also the function `nreverse', which is used more often.")
1243 (list)
1244 Lisp_Object list;
1245 {
1246 Lisp_Object new;
1247
1248 for (new = Qnil; CONSP (list); list = XCONS (list)->cdr)
1249 new = Fcons (XCONS (list)->car, new);
1250 if (!NILP (list))
1251 wrong_type_argument (Qconsp, list);
1252 return new;
1253 }
1254 \f
1255 Lisp_Object merge ();
1256
1257 DEFUN ("sort", Fsort, Ssort, 2, 2, 0,
1258 "Sort LIST, stably, comparing elements using PREDICATE.\n\
1259 Returns the sorted list. LIST is modified by side effects.\n\
1260 PREDICATE is called with two elements of LIST, and should return T\n\
1261 if the first element is \"less\" than the second.")
1262 (list, predicate)
1263 Lisp_Object list, predicate;
1264 {
1265 Lisp_Object front, back;
1266 register Lisp_Object len, tem;
1267 struct gcpro gcpro1, gcpro2;
1268 register int length;
1269
1270 front = list;
1271 len = Flength (list);
1272 length = XINT (len);
1273 if (length < 2)
1274 return list;
1275
1276 XSETINT (len, (length / 2) - 1);
1277 tem = Fnthcdr (len, list);
1278 back = Fcdr (tem);
1279 Fsetcdr (tem, Qnil);
1280
1281 GCPRO2 (front, back);
1282 front = Fsort (front, predicate);
1283 back = Fsort (back, predicate);
1284 UNGCPRO;
1285 return merge (front, back, predicate);
1286 }
1287
1288 Lisp_Object
1289 merge (org_l1, org_l2, pred)
1290 Lisp_Object org_l1, org_l2;
1291 Lisp_Object pred;
1292 {
1293 Lisp_Object value;
1294 register Lisp_Object tail;
1295 Lisp_Object tem;
1296 register Lisp_Object l1, l2;
1297 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1298
1299 l1 = org_l1;
1300 l2 = org_l2;
1301 tail = Qnil;
1302 value = Qnil;
1303
1304 /* It is sufficient to protect org_l1 and org_l2.
1305 When l1 and l2 are updated, we copy the new values
1306 back into the org_ vars. */
1307 GCPRO4 (org_l1, org_l2, pred, value);
1308
1309 while (1)
1310 {
1311 if (NILP (l1))
1312 {
1313 UNGCPRO;
1314 if (NILP (tail))
1315 return l2;
1316 Fsetcdr (tail, l2);
1317 return value;
1318 }
1319 if (NILP (l2))
1320 {
1321 UNGCPRO;
1322 if (NILP (tail))
1323 return l1;
1324 Fsetcdr (tail, l1);
1325 return value;
1326 }
1327 tem = call2 (pred, Fcar (l2), Fcar (l1));
1328 if (NILP (tem))
1329 {
1330 tem = l1;
1331 l1 = Fcdr (l1);
1332 org_l1 = l1;
1333 }
1334 else
1335 {
1336 tem = l2;
1337 l2 = Fcdr (l2);
1338 org_l2 = l2;
1339 }
1340 if (NILP (tail))
1341 value = tem;
1342 else
1343 Fsetcdr (tail, tem);
1344 tail = tem;
1345 }
1346 }
1347 \f
1348
1349 DEFUN ("plist-get", Fplist_get, Splist_get, 2, 2, 0,
1350 "Extract a value from a property list.\n\
1351 PLIST is a property list, which is a list of the form\n\
1352 \(PROP1 VALUE1 PROP2 VALUE2...). This function returns the value\n\
1353 corresponding to the given PROP, or nil if PROP is not\n\
1354 one of the properties on the list.")
1355 (plist, prop)
1356 Lisp_Object plist;
1357 register Lisp_Object prop;
1358 {
1359 register Lisp_Object tail;
1360 for (tail = plist; !NILP (tail); tail = Fcdr (XCONS (tail)->cdr))
1361 {
1362 register Lisp_Object tem;
1363 tem = Fcar (tail);
1364 if (EQ (prop, tem))
1365 return Fcar (XCONS (tail)->cdr);
1366 }
1367 return Qnil;
1368 }
1369
1370 DEFUN ("get", Fget, Sget, 2, 2, 0,
1371 "Return the value of SYMBOL's PROPNAME property.\n\
1372 This is the last value stored with `(put SYMBOL PROPNAME VALUE)'.")
1373 (symbol, propname)
1374 Lisp_Object symbol, propname;
1375 {
1376 CHECK_SYMBOL (symbol, 0);
1377 return Fplist_get (XSYMBOL (symbol)->plist, propname);
1378 }
1379
1380 DEFUN ("plist-put", Fplist_put, Splist_put, 3, 3, 0,
1381 "Change value in PLIST of PROP to VAL.\n\
1382 PLIST is a property list, which is a list of the form\n\
1383 \(PROP1 VALUE1 PROP2 VALUE2 ...). PROP is a symbol and VAL is any object.\n\
1384 If PROP is already a property on the list, its value is set to VAL,\n\
1385 otherwise the new PROP VAL pair is added. The new plist is returned;\n\
1386 use `(setq x (plist-put x prop val))' to be sure to use the new value.\n\
1387 The PLIST is modified by side effects.")
1388 (plist, prop, val)
1389 Lisp_Object plist;
1390 register Lisp_Object prop;
1391 Lisp_Object val;
1392 {
1393 register Lisp_Object tail, prev;
1394 Lisp_Object newcell;
1395 prev = Qnil;
1396 for (tail = plist; CONSP (tail) && CONSP (XCONS (tail)->cdr);
1397 tail = XCONS (XCONS (tail)->cdr)->cdr)
1398 {
1399 if (EQ (prop, XCONS (tail)->car))
1400 {
1401 Fsetcar (XCONS (tail)->cdr, val);
1402 return plist;
1403 }
1404 prev = tail;
1405 }
1406 newcell = Fcons (prop, Fcons (val, Qnil));
1407 if (NILP (prev))
1408 return newcell;
1409 else
1410 Fsetcdr (XCONS (prev)->cdr, newcell);
1411 return plist;
1412 }
1413
1414 DEFUN ("put", Fput, Sput, 3, 3, 0,
1415 "Store SYMBOL's PROPNAME property with value VALUE.\n\
1416 It can be retrieved with `(get SYMBOL PROPNAME)'.")
1417 (symbol, propname, value)
1418 Lisp_Object symbol, propname, value;
1419 {
1420 CHECK_SYMBOL (symbol, 0);
1421 XSYMBOL (symbol)->plist
1422 = Fplist_put (XSYMBOL (symbol)->plist, propname, value);
1423 return value;
1424 }
1425
1426 DEFUN ("equal", Fequal, Sequal, 2, 2, 0,
1427 "Return t if two Lisp objects have similar structure and contents.\n\
1428 They must have the same data type.\n\
1429 Conses are compared by comparing the cars and the cdrs.\n\
1430 Vectors and strings are compared element by element.\n\
1431 Numbers are compared by value, but integers cannot equal floats.\n\
1432 (Use `=' if you want integers and floats to be able to be equal.)\n\
1433 Symbols must match exactly.")
1434 (o1, o2)
1435 register Lisp_Object o1, o2;
1436 {
1437 return internal_equal (o1, o2, 0) ? Qt : Qnil;
1438 }
1439
1440 static int
1441 internal_equal (o1, o2, depth)
1442 register Lisp_Object o1, o2;
1443 int depth;
1444 {
1445 if (depth > 200)
1446 error ("Stack overflow in equal");
1447
1448 tail_recurse:
1449 QUIT;
1450 if (EQ (o1, o2))
1451 return 1;
1452 if (XTYPE (o1) != XTYPE (o2))
1453 return 0;
1454
1455 switch (XTYPE (o1))
1456 {
1457 #ifdef LISP_FLOAT_TYPE
1458 case Lisp_Float:
1459 return (extract_float (o1) == extract_float (o2));
1460 #endif
1461
1462 case Lisp_Cons:
1463 if (!internal_equal (XCONS (o1)->car, XCONS (o2)->car, depth + 1))
1464 return 0;
1465 o1 = XCONS (o1)->cdr;
1466 o2 = XCONS (o2)->cdr;
1467 goto tail_recurse;
1468
1469 case Lisp_Misc:
1470 if (XMISCTYPE (o1) != XMISCTYPE (o2))
1471 return 0;
1472 if (OVERLAYP (o1))
1473 {
1474 if (!internal_equal (OVERLAY_START (o1), OVERLAY_START (o1),
1475 depth + 1)
1476 || !internal_equal (OVERLAY_END (o1), OVERLAY_END (o1),
1477 depth + 1))
1478 return 0;
1479 o1 = XOVERLAY (o1)->plist;
1480 o2 = XOVERLAY (o2)->plist;
1481 goto tail_recurse;
1482 }
1483 if (MARKERP (o1))
1484 {
1485 return (XMARKER (o1)->buffer == XMARKER (o2)->buffer
1486 && (XMARKER (o1)->buffer == 0
1487 || XMARKER (o1)->bytepos == XMARKER (o2)->bytepos));
1488 }
1489 break;
1490
1491 case Lisp_Vectorlike:
1492 {
1493 register int i, size;
1494 size = XVECTOR (o1)->size;
1495 /* Pseudovectors have the type encoded in the size field, so this test
1496 actually checks that the objects have the same type as well as the
1497 same size. */
1498 if (XVECTOR (o2)->size != size)
1499 return 0;
1500 /* Boolvectors are compared much like strings. */
1501 if (BOOL_VECTOR_P (o1))
1502 {
1503 int size_in_chars
1504 = (XBOOL_VECTOR (o1)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
1505
1506 if (XBOOL_VECTOR (o1)->size != XBOOL_VECTOR (o2)->size)
1507 return 0;
1508 if (bcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
1509 size_in_chars))
1510 return 0;
1511 return 1;
1512 }
1513
1514 /* Aside from them, only true vectors, char-tables, and compiled
1515 functions are sensible to compare, so eliminate the others now. */
1516 if (size & PSEUDOVECTOR_FLAG)
1517 {
1518 if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE)))
1519 return 0;
1520 size &= PSEUDOVECTOR_SIZE_MASK;
1521 }
1522 for (i = 0; i < size; i++)
1523 {
1524 Lisp_Object v1, v2;
1525 v1 = XVECTOR (o1)->contents [i];
1526 v2 = XVECTOR (o2)->contents [i];
1527 if (!internal_equal (v1, v2, depth + 1))
1528 return 0;
1529 }
1530 return 1;
1531 }
1532 break;
1533
1534 case Lisp_String:
1535 if (XSTRING (o1)->size != XSTRING (o2)->size)
1536 return 0;
1537 if (XSTRING (o1)->size_byte != XSTRING (o2)->size_byte)
1538 return 0;
1539 if (bcmp (XSTRING (o1)->data, XSTRING (o2)->data,
1540 XSTRING (o1)->size_byte))
1541 return 0;
1542 return 1;
1543 }
1544 return 0;
1545 }
1546 \f
1547 extern Lisp_Object Fmake_char_internal ();
1548
1549 DEFUN ("fillarray", Ffillarray, Sfillarray, 2, 2, 0,
1550 "Store each element of ARRAY with ITEM.\n\
1551 ARRAY is a vector, string, char-table, or bool-vector.")
1552 (array, item)
1553 Lisp_Object array, item;
1554 {
1555 register int size, index, charval;
1556 retry:
1557 if (VECTORP (array))
1558 {
1559 register Lisp_Object *p = XVECTOR (array)->contents;
1560 size = XVECTOR (array)->size;
1561 for (index = 0; index < size; index++)
1562 p[index] = item;
1563 }
1564 else if (CHAR_TABLE_P (array))
1565 {
1566 register Lisp_Object *p = XCHAR_TABLE (array)->contents;
1567 size = CHAR_TABLE_ORDINARY_SLOTS;
1568 for (index = 0; index < size; index++)
1569 p[index] = item;
1570 XCHAR_TABLE (array)->defalt = Qnil;
1571 }
1572 else if (STRINGP (array))
1573 {
1574 register unsigned char *p = XSTRING (array)->data;
1575 CHECK_NUMBER (item, 1);
1576 charval = XINT (item);
1577 size = XSTRING (array)->size;
1578 for (index = 0; index < size; index++)
1579 p[index] = charval;
1580 }
1581 else if (BOOL_VECTOR_P (array))
1582 {
1583 register unsigned char *p = XBOOL_VECTOR (array)->data;
1584 int size_in_chars
1585 = (XBOOL_VECTOR (array)->size + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
1586
1587 charval = (! NILP (item) ? -1 : 0);
1588 for (index = 0; index < size_in_chars; index++)
1589 p[index] = charval;
1590 }
1591 else
1592 {
1593 array = wrong_type_argument (Qarrayp, array);
1594 goto retry;
1595 }
1596 return array;
1597 }
1598 \f
1599 DEFUN ("char-table-subtype", Fchar_table_subtype, Schar_table_subtype,
1600 1, 1, 0,
1601 "Return the subtype of char-table CHAR-TABLE. The value is a symbol.")
1602 (char_table)
1603 Lisp_Object char_table;
1604 {
1605 CHECK_CHAR_TABLE (char_table, 0);
1606
1607 return XCHAR_TABLE (char_table)->purpose;
1608 }
1609
1610 DEFUN ("char-table-parent", Fchar_table_parent, Schar_table_parent,
1611 1, 1, 0,
1612 "Return the parent char-table of CHAR-TABLE.\n\
1613 The value is either nil or another char-table.\n\
1614 If CHAR-TABLE holds nil for a given character,\n\
1615 then the actual applicable value is inherited from the parent char-table\n\
1616 \(or from its parents, if necessary).")
1617 (char_table)
1618 Lisp_Object char_table;
1619 {
1620 CHECK_CHAR_TABLE (char_table, 0);
1621
1622 return XCHAR_TABLE (char_table)->parent;
1623 }
1624
1625 DEFUN ("set-char-table-parent", Fset_char_table_parent, Sset_char_table_parent,
1626 2, 2, 0,
1627 "Set the parent char-table of CHAR-TABLE to PARENT.\n\
1628 PARENT must be either nil or another char-table.")
1629 (char_table, parent)
1630 Lisp_Object char_table, parent;
1631 {
1632 Lisp_Object temp;
1633
1634 CHECK_CHAR_TABLE (char_table, 0);
1635
1636 if (!NILP (parent))
1637 {
1638 CHECK_CHAR_TABLE (parent, 0);
1639
1640 for (temp = parent; !NILP (temp); temp = XCHAR_TABLE (temp)->parent)
1641 if (EQ (temp, char_table))
1642 error ("Attempt to make a chartable be its own parent");
1643 }
1644
1645 XCHAR_TABLE (char_table)->parent = parent;
1646
1647 return parent;
1648 }
1649
1650 DEFUN ("char-table-extra-slot", Fchar_table_extra_slot, Schar_table_extra_slot,
1651 2, 2, 0,
1652 "Return the value of CHAR-TABLE's extra-slot number N.")
1653 (char_table, n)
1654 Lisp_Object char_table, n;
1655 {
1656 CHECK_CHAR_TABLE (char_table, 1);
1657 CHECK_NUMBER (n, 2);
1658 if (XINT (n) < 0
1659 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1660 args_out_of_range (char_table, n);
1661
1662 return XCHAR_TABLE (char_table)->extras[XINT (n)];
1663 }
1664
1665 DEFUN ("set-char-table-extra-slot", Fset_char_table_extra_slot,
1666 Sset_char_table_extra_slot,
1667 3, 3, 0,
1668 "Set CHAR-TABLE's extra-slot number N to VALUE.")
1669 (char_table, n, value)
1670 Lisp_Object char_table, n, value;
1671 {
1672 CHECK_CHAR_TABLE (char_table, 1);
1673 CHECK_NUMBER (n, 2);
1674 if (XINT (n) < 0
1675 || XINT (n) >= CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (char_table)))
1676 args_out_of_range (char_table, n);
1677
1678 return XCHAR_TABLE (char_table)->extras[XINT (n)] = value;
1679 }
1680 \f
1681 DEFUN ("char-table-range", Fchar_table_range, Schar_table_range,
1682 2, 2, 0,
1683 "Return the value in CHAR-TABLE for a range of characters RANGE.\n\
1684 RANGE should be t (for all characters), nil (for the default value)\n\
1685 a vector which identifies a character set or a row of a character set,\n\
1686 or a character code.")
1687 (char_table, range)
1688 Lisp_Object char_table, range;
1689 {
1690 int i;
1691
1692 CHECK_CHAR_TABLE (char_table, 0);
1693
1694 if (EQ (range, Qnil))
1695 return XCHAR_TABLE (char_table)->defalt;
1696 else if (INTEGERP (range))
1697 return Faref (char_table, range);
1698 else if (VECTORP (range))
1699 {
1700 if (XVECTOR (range)->size == 1)
1701 return Faref (char_table, XVECTOR (range)->contents[0]);
1702 else
1703 {
1704 int size = XVECTOR (range)->size;
1705 Lisp_Object *val = XVECTOR (range)->contents;
1706 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1707 size <= 1 ? Qnil : val[1],
1708 size <= 2 ? Qnil : val[2]);
1709 return Faref (char_table, ch);
1710 }
1711 }
1712 else
1713 error ("Invalid RANGE argument to `char-table-range'");
1714 }
1715
1716 DEFUN ("set-char-table-range", Fset_char_table_range, Sset_char_table_range,
1717 3, 3, 0,
1718 "Set the value in CHAR-TABLE for a range of characters RANGE to VALUE.\n\
1719 RANGE should be t (for all characters), nil (for the default value)\n\
1720 a vector which identifies a character set or a row of a character set,\n\
1721 or a character code.")
1722 (char_table, range, value)
1723 Lisp_Object char_table, range, value;
1724 {
1725 int i;
1726
1727 CHECK_CHAR_TABLE (char_table, 0);
1728
1729 if (EQ (range, Qt))
1730 for (i = 0; i < CHAR_TABLE_ORDINARY_SLOTS; i++)
1731 XCHAR_TABLE (char_table)->contents[i] = value;
1732 else if (EQ (range, Qnil))
1733 XCHAR_TABLE (char_table)->defalt = value;
1734 else if (INTEGERP (range))
1735 Faset (char_table, range, value);
1736 else if (VECTORP (range))
1737 {
1738 if (XVECTOR (range)->size == 1)
1739 return Faset (char_table, XVECTOR (range)->contents[0], value);
1740 else
1741 {
1742 int size = XVECTOR (range)->size;
1743 Lisp_Object *val = XVECTOR (range)->contents;
1744 Lisp_Object ch = Fmake_char_internal (size <= 0 ? Qnil : val[0],
1745 size <= 1 ? Qnil : val[1],
1746 size <= 2 ? Qnil : val[2]);
1747 return Faset (char_table, ch, value);
1748 }
1749 }
1750 else
1751 error ("Invalid RANGE argument to `set-char-table-range'");
1752
1753 return value;
1754 }
1755
1756 DEFUN ("set-char-table-default", Fset_char_table_default,
1757 Sset_char_table_default, 3, 3, 0,
1758 "Set the default value in CHAR-TABLE for a generic character CHAR to VALUE.\n\
1759 The generic character specifies the group of characters.\n\
1760 See also the documentation of make-char.")
1761 (char_table, ch, value)
1762 Lisp_Object char_table, ch, value;
1763 {
1764 int c, i, charset, code1, code2;
1765 Lisp_Object temp;
1766
1767 CHECK_CHAR_TABLE (char_table, 0);
1768 CHECK_NUMBER (ch, 1);
1769
1770 c = XINT (ch);
1771 SPLIT_NON_ASCII_CHAR (c, charset, code1, code2);
1772 if (! CHARSET_DEFINED_P (charset))
1773 error ("Invalid character: %d", c);
1774
1775 if (charset == CHARSET_ASCII)
1776 return (XCHAR_TABLE (char_table)->defalt = value);
1777
1778 /* Even if C is not a generic char, we had better behave as if a
1779 generic char is specified. */
1780 if (CHARSET_DIMENSION (charset) == 1)
1781 code1 = 0;
1782 temp = XCHAR_TABLE (char_table)->contents[charset + 128];
1783 if (!code1)
1784 {
1785 if (SUB_CHAR_TABLE_P (temp))
1786 XCHAR_TABLE (temp)->defalt = value;
1787 else
1788 XCHAR_TABLE (char_table)->contents[charset + 128] = value;
1789 return value;
1790 }
1791 char_table = temp;
1792 if (! SUB_CHAR_TABLE_P (char_table))
1793 char_table = (XCHAR_TABLE (char_table)->contents[charset + 128]
1794 = make_sub_char_table (temp));
1795 temp = XCHAR_TABLE (char_table)->contents[code1];
1796 if (SUB_CHAR_TABLE_P (temp))
1797 XCHAR_TABLE (temp)->defalt = value;
1798 else
1799 XCHAR_TABLE (char_table)->contents[code1] = value;
1800 return value;
1801 }
1802 \f
1803 /* Map C_FUNCTION or FUNCTION over SUBTABLE, calling it for each
1804 character or group of characters that share a value.
1805 DEPTH is the current depth in the originally specified
1806 chartable, and INDICES contains the vector indices
1807 for the levels our callers have descended.
1808
1809 ARG is passed to C_FUNCTION when that is called. */
1810
1811 void
1812 map_char_table (c_function, function, subtable, arg, depth, indices)
1813 void (*c_function) P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
1814 Lisp_Object function, subtable, arg, *indices;
1815 int depth;
1816 {
1817 int i, to;
1818
1819 if (depth == 0)
1820 {
1821 /* At first, handle ASCII and 8-bit European characters. */
1822 for (i = 0; i < CHAR_TABLE_SINGLE_BYTE_SLOTS; i++)
1823 {
1824 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
1825 if (c_function)
1826 (*c_function) (arg, make_number (i), elt);
1827 else
1828 call2 (function, make_number (i), elt);
1829 }
1830 #if 0 /* If the char table has entries for higher characters,
1831 we should report them. */
1832 if (NILP (current_buffer->enable_multibyte_characters))
1833 return;
1834 #endif
1835 to = CHAR_TABLE_ORDINARY_SLOTS;
1836 }
1837 else
1838 {
1839 i = 32;
1840 to = SUB_CHAR_TABLE_ORDINARY_SLOTS;
1841 }
1842
1843 for (; i < to; i++)
1844 {
1845 Lisp_Object elt = XCHAR_TABLE (subtable)->contents[i];
1846
1847 XSETFASTINT (indices[depth], i);
1848
1849 if (SUB_CHAR_TABLE_P (elt))
1850 {
1851 if (depth >= 3)
1852 error ("Too deep char table");
1853 map_char_table (c_function, function, elt, arg, depth + 1, indices);
1854 }
1855 else
1856 {
1857 int charset = XFASTINT (indices[0]) - 128, c1, c2, c;
1858
1859 if (CHARSET_DEFINED_P (charset))
1860 {
1861 c1 = depth >= 1 ? XFASTINT (indices[1]) : 0;
1862 c2 = depth >= 2 ? XFASTINT (indices[2]) : 0;
1863 c = MAKE_NON_ASCII_CHAR (charset, c1, c2);
1864 if (c_function)
1865 (*c_function) (arg, make_number (c), elt);
1866 else
1867 call2 (function, make_number (c), elt);
1868 }
1869 }
1870 }
1871 }
1872
1873 DEFUN ("map-char-table", Fmap_char_table, Smap_char_table,
1874 2, 2, 0,
1875 "Call FUNCTION for each (normal and generic) characters in CHAR-TABLE.\n\
1876 FUNCTION is called with two arguments--a key and a value.\n\
1877 The key is always a possible IDX argument to `aref'.")
1878 (function, char_table)
1879 Lisp_Object function, char_table;
1880 {
1881 /* The depth of char table is at most 3. */
1882 Lisp_Object indices[3];
1883
1884 CHECK_CHAR_TABLE (char_table, 1);
1885
1886 map_char_table (NULL, function, char_table, char_table, 0, indices);
1887 return Qnil;
1888 }
1889 \f
1890 /* ARGSUSED */
1891 Lisp_Object
1892 nconc2 (s1, s2)
1893 Lisp_Object s1, s2;
1894 {
1895 #ifdef NO_ARG_ARRAY
1896 Lisp_Object args[2];
1897 args[0] = s1;
1898 args[1] = s2;
1899 return Fnconc (2, args);
1900 #else
1901 return Fnconc (2, &s1);
1902 #endif /* NO_ARG_ARRAY */
1903 }
1904
1905 DEFUN ("nconc", Fnconc, Snconc, 0, MANY, 0,
1906 "Concatenate any number of lists by altering them.\n\
1907 Only the last argument is not altered, and need not be a list.")
1908 (nargs, args)
1909 int nargs;
1910 Lisp_Object *args;
1911 {
1912 register int argnum;
1913 register Lisp_Object tail, tem, val;
1914
1915 val = Qnil;
1916
1917 for (argnum = 0; argnum < nargs; argnum++)
1918 {
1919 tem = args[argnum];
1920 if (NILP (tem)) continue;
1921
1922 if (NILP (val))
1923 val = tem;
1924
1925 if (argnum + 1 == nargs) break;
1926
1927 if (!CONSP (tem))
1928 tem = wrong_type_argument (Qlistp, tem);
1929
1930 while (CONSP (tem))
1931 {
1932 tail = tem;
1933 tem = Fcdr (tail);
1934 QUIT;
1935 }
1936
1937 tem = args[argnum + 1];
1938 Fsetcdr (tail, tem);
1939 if (NILP (tem))
1940 args[argnum + 1] = tail;
1941 }
1942
1943 return val;
1944 }
1945 \f
1946 /* This is the guts of all mapping functions.
1947 Apply FN to each element of SEQ, one by one,
1948 storing the results into elements of VALS, a C vector of Lisp_Objects.
1949 LENI is the length of VALS, which should also be the length of SEQ. */
1950
1951 static void
1952 mapcar1 (leni, vals, fn, seq)
1953 int leni;
1954 Lisp_Object *vals;
1955 Lisp_Object fn, seq;
1956 {
1957 register Lisp_Object tail;
1958 Lisp_Object dummy;
1959 register int i;
1960 struct gcpro gcpro1, gcpro2, gcpro3;
1961
1962 /* Don't let vals contain any garbage when GC happens. */
1963 for (i = 0; i < leni; i++)
1964 vals[i] = Qnil;
1965
1966 GCPRO3 (dummy, fn, seq);
1967 gcpro1.var = vals;
1968 gcpro1.nvars = leni;
1969 /* We need not explicitly protect `tail' because it is used only on lists, and
1970 1) lists are not relocated and 2) the list is marked via `seq' so will not be freed */
1971
1972 if (VECTORP (seq))
1973 {
1974 for (i = 0; i < leni; i++)
1975 {
1976 dummy = XVECTOR (seq)->contents[i];
1977 vals[i] = call1 (fn, dummy);
1978 }
1979 }
1980 else if (STRINGP (seq) && ! STRING_MULTIBYTE (seq))
1981 {
1982 /* Single-byte string. */
1983 for (i = 0; i < leni; i++)
1984 {
1985 XSETFASTINT (dummy, XSTRING (seq)->data[i]);
1986 vals[i] = call1 (fn, dummy);
1987 }
1988 }
1989 else if (STRINGP (seq))
1990 {
1991 /* Multi-byte string. */
1992 int len_byte = XSTRING (seq)->size_byte;
1993 int i_byte;
1994
1995 for (i = 0, i_byte = 0; i < leni;)
1996 {
1997 int c;
1998 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte)
1999 XSETFASTINT (dummy, c);
2000 vals[i] = call1 (fn, dummy);
2001 }
2002 }
2003 else /* Must be a list, since Flength did not get an error */
2004 {
2005 tail = seq;
2006 for (i = 0; i < leni; i++)
2007 {
2008 vals[i] = call1 (fn, Fcar (tail));
2009 tail = XCONS (tail)->cdr;
2010 }
2011 }
2012
2013 UNGCPRO;
2014 }
2015
2016 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
2017 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2018 In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
2019 SEPARATOR results in spaces between the values returned by FUNCTION.")
2020 (function, sequence, separator)
2021 Lisp_Object function, sequence, separator;
2022 {
2023 Lisp_Object len;
2024 register int leni;
2025 int nargs;
2026 register Lisp_Object *args;
2027 register int i;
2028 struct gcpro gcpro1;
2029
2030 len = Flength (sequence);
2031 leni = XINT (len);
2032 nargs = leni + leni - 1;
2033 if (nargs < 0) return build_string ("");
2034
2035 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2036
2037 GCPRO1 (separator);
2038 mapcar1 (leni, args, function, sequence);
2039 UNGCPRO;
2040
2041 for (i = leni - 1; i >= 0; i--)
2042 args[i + i] = args[i];
2043
2044 for (i = 1; i < nargs; i += 2)
2045 args[i] = separator;
2046
2047 return Fconcat (nargs, args);
2048 }
2049
2050 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2051 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2052 The result is a list just as long as SEQUENCE.\n\
2053 SEQUENCE may be a list, a vector or a string.")
2054 (function, sequence)
2055 Lisp_Object function, sequence;
2056 {
2057 register Lisp_Object len;
2058 register int leni;
2059 register Lisp_Object *args;
2060
2061 len = Flength (sequence);
2062 leni = XFASTINT (len);
2063 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2064
2065 mapcar1 (leni, args, function, sequence);
2066
2067 return Flist (leni, args);
2068 }
2069 \f
2070 /* Anything that calls this function must protect from GC! */
2071
2072 DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2073 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
2074 Takes one argument, which is the string to display to ask the question.\n\
2075 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
2076 No confirmation of the answer is requested; a single character is enough.\n\
2077 Also accepts Space to mean yes, or Delete to mean no.")
2078 (prompt)
2079 Lisp_Object prompt;
2080 {
2081 register Lisp_Object obj, key, def, answer_string, map;
2082 register int answer;
2083 Lisp_Object xprompt;
2084 Lisp_Object args[2];
2085 struct gcpro gcpro1, gcpro2;
2086 int count = specpdl_ptr - specpdl;
2087
2088 specbind (Qcursor_in_echo_area, Qt);
2089
2090 map = Fsymbol_value (intern ("query-replace-map"));
2091
2092 CHECK_STRING (prompt, 0);
2093 xprompt = prompt;
2094 GCPRO2 (prompt, xprompt);
2095
2096 while (1)
2097 {
2098
2099 #ifdef HAVE_MENUS
2100 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2101 && use_dialog_box
2102 && have_menus_p ())
2103 {
2104 Lisp_Object pane, menu;
2105 redisplay_preserve_echo_area ();
2106 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2107 Fcons (Fcons (build_string ("No"), Qnil),
2108 Qnil));
2109 menu = Fcons (prompt, pane);
2110 obj = Fx_popup_dialog (Qt, menu);
2111 answer = !NILP (obj);
2112 break;
2113 }
2114 #endif /* HAVE_MENUS */
2115 cursor_in_echo_area = 1;
2116 choose_minibuf_frame ();
2117 message_with_string ("%s(y or n) ", xprompt, 0);
2118
2119 if (minibuffer_auto_raise)
2120 {
2121 Lisp_Object mini_frame;
2122
2123 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2124
2125 Fraise_frame (mini_frame);
2126 }
2127
2128 obj = read_filtered_event (1, 0, 0);
2129 cursor_in_echo_area = 0;
2130 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2131 QUIT;
2132
2133 key = Fmake_vector (make_number (1), obj);
2134 def = Flookup_key (map, key, Qt);
2135 answer_string = Fsingle_key_description (obj);
2136
2137 if (EQ (def, intern ("skip")))
2138 {
2139 answer = 0;
2140 break;
2141 }
2142 else if (EQ (def, intern ("act")))
2143 {
2144 answer = 1;
2145 break;
2146 }
2147 else if (EQ (def, intern ("recenter")))
2148 {
2149 Frecenter (Qnil);
2150 xprompt = prompt;
2151 continue;
2152 }
2153 else if (EQ (def, intern ("quit")))
2154 Vquit_flag = Qt;
2155 /* We want to exit this command for exit-prefix,
2156 and this is the only way to do it. */
2157 else if (EQ (def, intern ("exit-prefix")))
2158 Vquit_flag = Qt;
2159
2160 QUIT;
2161
2162 /* If we don't clear this, then the next call to read_char will
2163 return quit_char again, and we'll enter an infinite loop. */
2164 Vquit_flag = Qnil;
2165
2166 Fding (Qnil);
2167 Fdiscard_input ();
2168 if (EQ (xprompt, prompt))
2169 {
2170 args[0] = build_string ("Please answer y or n. ");
2171 args[1] = prompt;
2172 xprompt = Fconcat (2, args);
2173 }
2174 }
2175 UNGCPRO;
2176
2177 if (! noninteractive)
2178 {
2179 cursor_in_echo_area = -1;
2180 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2181 xprompt, 0);
2182 }
2183
2184 unbind_to (count, Qnil);
2185 return answer ? Qt : Qnil;
2186 }
2187 \f
2188 /* This is how C code calls `yes-or-no-p' and allows the user
2189 to redefined it.
2190
2191 Anything that calls this function must protect from GC! */
2192
2193 Lisp_Object
2194 do_yes_or_no_p (prompt)
2195 Lisp_Object prompt;
2196 {
2197 return call1 (intern ("yes-or-no-p"), prompt);
2198 }
2199
2200 /* Anything that calls this function must protect from GC! */
2201
2202 DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
2203 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2204 Takes one argument, which is the string to display to ask the question.\n\
2205 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2206 The user must confirm the answer with RET,\n\
2207 and can edit it until it has been confirmed.")
2208 (prompt)
2209 Lisp_Object prompt;
2210 {
2211 register Lisp_Object ans;
2212 Lisp_Object args[2];
2213 struct gcpro gcpro1;
2214 Lisp_Object menu;
2215
2216 CHECK_STRING (prompt, 0);
2217
2218 #ifdef HAVE_MENUS
2219 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2220 && use_dialog_box
2221 && have_menus_p ())
2222 {
2223 Lisp_Object pane, menu, obj;
2224 redisplay_preserve_echo_area ();
2225 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2226 Fcons (Fcons (build_string ("No"), Qnil),
2227 Qnil));
2228 GCPRO1 (pane);
2229 menu = Fcons (prompt, pane);
2230 obj = Fx_popup_dialog (Qt, menu);
2231 UNGCPRO;
2232 return obj;
2233 }
2234 #endif /* HAVE_MENUS */
2235
2236 args[0] = prompt;
2237 args[1] = build_string ("(yes or no) ");
2238 prompt = Fconcat (2, args);
2239
2240 GCPRO1 (prompt);
2241
2242 while (1)
2243 {
2244 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
2245 Qyes_or_no_p_history, Qnil,
2246 Qnil));
2247 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2248 {
2249 UNGCPRO;
2250 return Qt;
2251 }
2252 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2253 {
2254 UNGCPRO;
2255 return Qnil;
2256 }
2257
2258 Fding (Qnil);
2259 Fdiscard_input ();
2260 message ("Please answer yes or no.");
2261 Fsleep_for (make_number (2), Qnil);
2262 }
2263 }
2264 \f
2265 DEFUN ("load-average", Fload_average, Sload_average, 0, 0, 0,
2266 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2267 Each of the three load averages is multiplied by 100,\n\
2268 then converted to integer.\n\
2269 If the 5-minute or 15-minute load averages are not available, return a\n\
2270 shortened list, containing only those averages which are available.")
2271 ()
2272 {
2273 double load_ave[3];
2274 int loads = getloadavg (load_ave, 3);
2275 Lisp_Object ret;
2276
2277 if (loads < 0)
2278 error ("load-average not implemented for this operating system");
2279
2280 ret = Qnil;
2281 while (loads > 0)
2282 ret = Fcons (make_number ((int) (load_ave[--loads] * 100.0)), ret);
2283
2284 return ret;
2285 }
2286 \f
2287 Lisp_Object Vfeatures;
2288
2289 DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2290 "Returns t if FEATURE is present in this Emacs.\n\
2291 Use this to conditionalize execution of lisp code based on the presence or\n\
2292 absence of emacs or environment extensions.\n\
2293 Use `provide' to declare that a feature is available.\n\
2294 This function looks at the value of the variable `features'.")
2295 (feature)
2296 Lisp_Object feature;
2297 {
2298 register Lisp_Object tem;
2299 CHECK_SYMBOL (feature, 0);
2300 tem = Fmemq (feature, Vfeatures);
2301 return (NILP (tem)) ? Qnil : Qt;
2302 }
2303
2304 DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2305 "Announce that FEATURE is a feature of the current Emacs.")
2306 (feature)
2307 Lisp_Object feature;
2308 {
2309 register Lisp_Object tem;
2310 CHECK_SYMBOL (feature, 0);
2311 if (!NILP (Vautoload_queue))
2312 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2313 tem = Fmemq (feature, Vfeatures);
2314 if (NILP (tem))
2315 Vfeatures = Fcons (feature, Vfeatures);
2316 LOADHIST_ATTACH (Fcons (Qprovide, feature));
2317 return feature;
2318 }
2319
2320 DEFUN ("require", Frequire, Srequire, 1, 2, 0,
2321 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2322 If FEATURE is not a member of the list `features', then the feature\n\
2323 is not loaded; so load the file FILENAME.\n\
2324 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
2325 (feature, file_name)
2326 Lisp_Object feature, file_name;
2327 {
2328 register Lisp_Object tem;
2329 CHECK_SYMBOL (feature, 0);
2330 tem = Fmemq (feature, Vfeatures);
2331 LOADHIST_ATTACH (Fcons (Qrequire, feature));
2332 if (NILP (tem))
2333 {
2334 int count = specpdl_ptr - specpdl;
2335
2336 /* Value saved here is to be restored into Vautoload_queue */
2337 record_unwind_protect (un_autoload, Vautoload_queue);
2338 Vautoload_queue = Qt;
2339
2340 Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
2341 Qnil, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
2342
2343 tem = Fmemq (feature, Vfeatures);
2344 if (NILP (tem))
2345 error ("Required feature %s was not provided",
2346 XSYMBOL (feature)->name->data);
2347
2348 /* Once loading finishes, don't undo it. */
2349 Vautoload_queue = Qt;
2350 feature = unbind_to (count, feature);
2351 }
2352 return feature;
2353 }
2354 \f
2355 /* Primitives for work of the "widget" library.
2356 In an ideal world, this section would not have been necessary.
2357 However, lisp function calls being as slow as they are, it turns
2358 out that some functions in the widget library (wid-edit.el) are the
2359 bottleneck of Widget operation. Here is their translation to C,
2360 for the sole reason of efficiency. */
2361
2362 DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2363 "Return non-nil if PLIST has the property PROP.\n\
2364 PLIST is a property list, which is a list of the form\n\
2365 \(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2366 Unlike `plist-get', this allows you to distinguish between a missing\n\
2367 property and a property with the value nil.\n\
2368 The value is actually the tail of PLIST whose car is PROP.")
2369 (plist, prop)
2370 Lisp_Object plist, prop;
2371 {
2372 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2373 {
2374 QUIT;
2375 plist = XCDR (plist);
2376 plist = CDR (plist);
2377 }
2378 return plist;
2379 }
2380
2381 DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2382 "In WIDGET, set PROPERTY to VALUE.\n\
2383 The value can later be retrieved with `widget-get'.")
2384 (widget, property, value)
2385 Lisp_Object widget, property, value;
2386 {
2387 CHECK_CONS (widget, 1);
2388 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
2389 }
2390
2391 DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2392 "In WIDGET, get the value of PROPERTY.\n\
2393 The value could either be specified when the widget was created, or\n\
2394 later with `widget-put'.")
2395 (widget, property)
2396 Lisp_Object widget, property;
2397 {
2398 Lisp_Object tmp;
2399
2400 while (1)
2401 {
2402 if (NILP (widget))
2403 return Qnil;
2404 CHECK_CONS (widget, 1);
2405 tmp = Fwidget_plist_member (XCDR (widget), property);
2406 if (CONSP (tmp))
2407 {
2408 tmp = XCDR (tmp);
2409 return CAR (tmp);
2410 }
2411 tmp = XCAR (widget);
2412 if (NILP (tmp))
2413 return Qnil;
2414 widget = Fget (tmp, Qwidget_type);
2415 }
2416 }
2417
2418 DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
2419 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
2420 ARGS are passed as extra arguments to the function.")
2421 (nargs, args)
2422 int nargs;
2423 Lisp_Object *args;
2424 {
2425 /* This function can GC. */
2426 Lisp_Object newargs[3];
2427 struct gcpro gcpro1, gcpro2;
2428 Lisp_Object result;
2429
2430 newargs[0] = Fwidget_get (args[0], args[1]);
2431 newargs[1] = args[0];
2432 newargs[2] = Flist (nargs - 2, args + 2);
2433 GCPRO2 (newargs[0], newargs[2]);
2434 result = Fapply (3, newargs);
2435 UNGCPRO;
2436 return result;
2437 }
2438 \f
2439 syms_of_fns ()
2440 {
2441 Qstring_lessp = intern ("string-lessp");
2442 staticpro (&Qstring_lessp);
2443 Qprovide = intern ("provide");
2444 staticpro (&Qprovide);
2445 Qrequire = intern ("require");
2446 staticpro (&Qrequire);
2447 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
2448 staticpro (&Qyes_or_no_p_history);
2449 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
2450 staticpro (&Qcursor_in_echo_area);
2451 Qwidget_type = intern ("widget-type");
2452 staticpro (&Qwidget_type);
2453
2454 staticpro (&string_char_byte_cache_string);
2455 string_char_byte_cache_string = Qnil;
2456
2457 Fset (Qyes_or_no_p_history, Qnil);
2458
2459 DEFVAR_LISP ("features", &Vfeatures,
2460 "A list of symbols which are the features of the executing emacs.\n\
2461 Used by `featurep' and `require', and altered by `provide'.");
2462 Vfeatures = Qnil;
2463
2464 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
2465 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
2466 This applies to y-or-n and yes-or-no questions asked by commands\n\
2467 invoked by mouse clicks and mouse menu items.");
2468 use_dialog_box = 1;
2469
2470 defsubr (&Sidentity);
2471 defsubr (&Srandom);
2472 defsubr (&Slength);
2473 defsubr (&Ssafe_length);
2474 defsubr (&Sstring_equal);
2475 defsubr (&Sstring_lessp);
2476 defsubr (&Sappend);
2477 defsubr (&Sconcat);
2478 defsubr (&Svconcat);
2479 defsubr (&Scopy_sequence);
2480 defsubr (&Sstring_make_multibyte);
2481 defsubr (&Sstring_make_unibyte);
2482 defsubr (&Scopy_alist);
2483 defsubr (&Ssubstring);
2484 defsubr (&Snthcdr);
2485 defsubr (&Snth);
2486 defsubr (&Selt);
2487 defsubr (&Smember);
2488 defsubr (&Smemq);
2489 defsubr (&Sassq);
2490 defsubr (&Sassoc);
2491 defsubr (&Srassq);
2492 defsubr (&Srassoc);
2493 defsubr (&Sdelq);
2494 defsubr (&Sdelete);
2495 defsubr (&Snreverse);
2496 defsubr (&Sreverse);
2497 defsubr (&Ssort);
2498 defsubr (&Splist_get);
2499 defsubr (&Sget);
2500 defsubr (&Splist_put);
2501 defsubr (&Sput);
2502 defsubr (&Sequal);
2503 defsubr (&Sfillarray);
2504 defsubr (&Schar_table_subtype);
2505 defsubr (&Schar_table_parent);
2506 defsubr (&Sset_char_table_parent);
2507 defsubr (&Schar_table_extra_slot);
2508 defsubr (&Sset_char_table_extra_slot);
2509 defsubr (&Schar_table_range);
2510 defsubr (&Sset_char_table_range);
2511 defsubr (&Sset_char_table_default);
2512 defsubr (&Smap_char_table);
2513 defsubr (&Snconc);
2514 defsubr (&Smapcar);
2515 defsubr (&Smapconcat);
2516 defsubr (&Sy_or_n_p);
2517 defsubr (&Syes_or_no_p);
2518 defsubr (&Sload_average);
2519 defsubr (&Sfeaturep);
2520 defsubr (&Srequire);
2521 defsubr (&Sprovide);
2522 defsubr (&Swidget_plist_member);
2523 defsubr (&Swidget_put);
2524 defsubr (&Swidget_get);
2525 defsubr (&Swidget_apply);
2526 }