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