]> code.delx.au - gnu-emacs/blob - src/fns.c
(mapcar1): Keep `i' in `i_before' before `i' is
[gnu-emacs] / 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 int i_before = i;
1999
2000 FETCH_STRING_CHAR_ADVANCE (c, seq, i, i_byte);
2001 XSETFASTINT (dummy, c);
2002 vals[i_before] = call1 (fn, dummy);
2003 }
2004 }
2005 else /* Must be a list, since Flength did not get an error */
2006 {
2007 tail = seq;
2008 for (i = 0; i < leni; i++)
2009 {
2010 vals[i] = call1 (fn, Fcar (tail));
2011 tail = XCONS (tail)->cdr;
2012 }
2013 }
2014
2015 UNGCPRO;
2016 }
2017
2018 DEFUN ("mapconcat", Fmapconcat, Smapconcat, 3, 3, 0,
2019 "Apply FUNCTION to each element of SEQUENCE, and concat the results as strings.\n\
2020 In between each pair of results, stick in SEPARATOR. Thus, \" \" as\n\
2021 SEPARATOR results in spaces between the values returned by FUNCTION.")
2022 (function, sequence, separator)
2023 Lisp_Object function, sequence, separator;
2024 {
2025 Lisp_Object len;
2026 register int leni;
2027 int nargs;
2028 register Lisp_Object *args;
2029 register int i;
2030 struct gcpro gcpro1;
2031
2032 len = Flength (sequence);
2033 leni = XINT (len);
2034 nargs = leni + leni - 1;
2035 if (nargs < 0) return build_string ("");
2036
2037 args = (Lisp_Object *) alloca (nargs * sizeof (Lisp_Object));
2038
2039 GCPRO1 (separator);
2040 mapcar1 (leni, args, function, sequence);
2041 UNGCPRO;
2042
2043 for (i = leni - 1; i >= 0; i--)
2044 args[i + i] = args[i];
2045
2046 for (i = 1; i < nargs; i += 2)
2047 args[i] = separator;
2048
2049 return Fconcat (nargs, args);
2050 }
2051
2052 DEFUN ("mapcar", Fmapcar, Smapcar, 2, 2, 0,
2053 "Apply FUNCTION to each element of SEQUENCE, and make a list of the results.\n\
2054 The result is a list just as long as SEQUENCE.\n\
2055 SEQUENCE may be a list, a vector or a string.")
2056 (function, sequence)
2057 Lisp_Object function, sequence;
2058 {
2059 register Lisp_Object len;
2060 register int leni;
2061 register Lisp_Object *args;
2062
2063 len = Flength (sequence);
2064 leni = XFASTINT (len);
2065 args = (Lisp_Object *) alloca (leni * sizeof (Lisp_Object));
2066
2067 mapcar1 (leni, args, function, sequence);
2068
2069 return Flist (leni, args);
2070 }
2071 \f
2072 /* Anything that calls this function must protect from GC! */
2073
2074 DEFUN ("y-or-n-p", Fy_or_n_p, Sy_or_n_p, 1, 1, 0,
2075 "Ask user a \"y or n\" question. Return t if answer is \"y\".\n\
2076 Takes one argument, which is the string to display to ask the question.\n\
2077 It should end in a space; `y-or-n-p' adds `(y or n) ' to it.\n\
2078 No confirmation of the answer is requested; a single character is enough.\n\
2079 Also accepts Space to mean yes, or Delete to mean no.")
2080 (prompt)
2081 Lisp_Object prompt;
2082 {
2083 register Lisp_Object obj, key, def, answer_string, map;
2084 register int answer;
2085 Lisp_Object xprompt;
2086 Lisp_Object args[2];
2087 struct gcpro gcpro1, gcpro2;
2088 int count = specpdl_ptr - specpdl;
2089
2090 specbind (Qcursor_in_echo_area, Qt);
2091
2092 map = Fsymbol_value (intern ("query-replace-map"));
2093
2094 CHECK_STRING (prompt, 0);
2095 xprompt = prompt;
2096 GCPRO2 (prompt, xprompt);
2097
2098 while (1)
2099 {
2100
2101 #ifdef HAVE_MENUS
2102 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2103 && use_dialog_box
2104 && have_menus_p ())
2105 {
2106 Lisp_Object pane, menu;
2107 redisplay_preserve_echo_area ();
2108 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2109 Fcons (Fcons (build_string ("No"), Qnil),
2110 Qnil));
2111 menu = Fcons (prompt, pane);
2112 obj = Fx_popup_dialog (Qt, menu);
2113 answer = !NILP (obj);
2114 break;
2115 }
2116 #endif /* HAVE_MENUS */
2117 cursor_in_echo_area = 1;
2118 choose_minibuf_frame ();
2119 message_with_string ("%s(y or n) ", xprompt, 0);
2120
2121 if (minibuffer_auto_raise)
2122 {
2123 Lisp_Object mini_frame;
2124
2125 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
2126
2127 Fraise_frame (mini_frame);
2128 }
2129
2130 obj = read_filtered_event (1, 0, 0);
2131 cursor_in_echo_area = 0;
2132 /* If we need to quit, quit with cursor_in_echo_area = 0. */
2133 QUIT;
2134
2135 key = Fmake_vector (make_number (1), obj);
2136 def = Flookup_key (map, key, Qt);
2137 answer_string = Fsingle_key_description (obj);
2138
2139 if (EQ (def, intern ("skip")))
2140 {
2141 answer = 0;
2142 break;
2143 }
2144 else if (EQ (def, intern ("act")))
2145 {
2146 answer = 1;
2147 break;
2148 }
2149 else if (EQ (def, intern ("recenter")))
2150 {
2151 Frecenter (Qnil);
2152 xprompt = prompt;
2153 continue;
2154 }
2155 else if (EQ (def, intern ("quit")))
2156 Vquit_flag = Qt;
2157 /* We want to exit this command for exit-prefix,
2158 and this is the only way to do it. */
2159 else if (EQ (def, intern ("exit-prefix")))
2160 Vquit_flag = Qt;
2161
2162 QUIT;
2163
2164 /* If we don't clear this, then the next call to read_char will
2165 return quit_char again, and we'll enter an infinite loop. */
2166 Vquit_flag = Qnil;
2167
2168 Fding (Qnil);
2169 Fdiscard_input ();
2170 if (EQ (xprompt, prompt))
2171 {
2172 args[0] = build_string ("Please answer y or n. ");
2173 args[1] = prompt;
2174 xprompt = Fconcat (2, args);
2175 }
2176 }
2177 UNGCPRO;
2178
2179 if (! noninteractive)
2180 {
2181 cursor_in_echo_area = -1;
2182 message_with_string (answer ? "%s(y or n) y" : "%s(y or n) n",
2183 xprompt, 0);
2184 }
2185
2186 unbind_to (count, Qnil);
2187 return answer ? Qt : Qnil;
2188 }
2189 \f
2190 /* This is how C code calls `yes-or-no-p' and allows the user
2191 to redefined it.
2192
2193 Anything that calls this function must protect from GC! */
2194
2195 Lisp_Object
2196 do_yes_or_no_p (prompt)
2197 Lisp_Object prompt;
2198 {
2199 return call1 (intern ("yes-or-no-p"), prompt);
2200 }
2201
2202 /* Anything that calls this function must protect from GC! */
2203
2204 DEFUN ("yes-or-no-p", Fyes_or_no_p, Syes_or_no_p, 1, 1, 0,
2205 "Ask user a yes-or-no question. Return t if answer is yes.\n\
2206 Takes one argument, which is the string to display to ask the question.\n\
2207 It should end in a space; `yes-or-no-p' adds `(yes or no) ' to it.\n\
2208 The user must confirm the answer with RET,\n\
2209 and can edit it until it has been confirmed.")
2210 (prompt)
2211 Lisp_Object prompt;
2212 {
2213 register Lisp_Object ans;
2214 Lisp_Object args[2];
2215 struct gcpro gcpro1;
2216 Lisp_Object menu;
2217
2218 CHECK_STRING (prompt, 0);
2219
2220 #ifdef HAVE_MENUS
2221 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
2222 && use_dialog_box
2223 && have_menus_p ())
2224 {
2225 Lisp_Object pane, menu, obj;
2226 redisplay_preserve_echo_area ();
2227 pane = Fcons (Fcons (build_string ("Yes"), Qt),
2228 Fcons (Fcons (build_string ("No"), Qnil),
2229 Qnil));
2230 GCPRO1 (pane);
2231 menu = Fcons (prompt, pane);
2232 obj = Fx_popup_dialog (Qt, menu);
2233 UNGCPRO;
2234 return obj;
2235 }
2236 #endif /* HAVE_MENUS */
2237
2238 args[0] = prompt;
2239 args[1] = build_string ("(yes or no) ");
2240 prompt = Fconcat (2, args);
2241
2242 GCPRO1 (prompt);
2243
2244 while (1)
2245 {
2246 ans = Fdowncase (Fread_from_minibuffer (prompt, Qnil, Qnil, Qnil,
2247 Qyes_or_no_p_history, Qnil,
2248 Qnil));
2249 if (XSTRING (ans)->size == 3 && !strcmp (XSTRING (ans)->data, "yes"))
2250 {
2251 UNGCPRO;
2252 return Qt;
2253 }
2254 if (XSTRING (ans)->size == 2 && !strcmp (XSTRING (ans)->data, "no"))
2255 {
2256 UNGCPRO;
2257 return Qnil;
2258 }
2259
2260 Fding (Qnil);
2261 Fdiscard_input ();
2262 message ("Please answer yes or no.");
2263 Fsleep_for (make_number (2), Qnil);
2264 }
2265 }
2266 \f
2267 DEFUN ("load-average", Fload_average, Sload_average, 0, 0, 0,
2268 "Return list of 1 minute, 5 minute and 15 minute load averages.\n\
2269 Each of the three load averages is multiplied by 100,\n\
2270 then converted to integer.\n\
2271 If the 5-minute or 15-minute load averages are not available, return a\n\
2272 shortened list, containing only those averages which are available.")
2273 ()
2274 {
2275 double load_ave[3];
2276 int loads = getloadavg (load_ave, 3);
2277 Lisp_Object ret;
2278
2279 if (loads < 0)
2280 error ("load-average not implemented for this operating system");
2281
2282 ret = Qnil;
2283 while (loads > 0)
2284 ret = Fcons (make_number ((int) (load_ave[--loads] * 100.0)), ret);
2285
2286 return ret;
2287 }
2288 \f
2289 Lisp_Object Vfeatures;
2290
2291 DEFUN ("featurep", Ffeaturep, Sfeaturep, 1, 1, 0,
2292 "Returns t if FEATURE is present in this Emacs.\n\
2293 Use this to conditionalize execution of lisp code based on the presence or\n\
2294 absence of emacs or environment extensions.\n\
2295 Use `provide' to declare that a feature is available.\n\
2296 This function looks at the value of the variable `features'.")
2297 (feature)
2298 Lisp_Object feature;
2299 {
2300 register Lisp_Object tem;
2301 CHECK_SYMBOL (feature, 0);
2302 tem = Fmemq (feature, Vfeatures);
2303 return (NILP (tem)) ? Qnil : Qt;
2304 }
2305
2306 DEFUN ("provide", Fprovide, Sprovide, 1, 1, 0,
2307 "Announce that FEATURE is a feature of the current Emacs.")
2308 (feature)
2309 Lisp_Object feature;
2310 {
2311 register Lisp_Object tem;
2312 CHECK_SYMBOL (feature, 0);
2313 if (!NILP (Vautoload_queue))
2314 Vautoload_queue = Fcons (Fcons (Vfeatures, Qnil), Vautoload_queue);
2315 tem = Fmemq (feature, Vfeatures);
2316 if (NILP (tem))
2317 Vfeatures = Fcons (feature, Vfeatures);
2318 LOADHIST_ATTACH (Fcons (Qprovide, feature));
2319 return feature;
2320 }
2321
2322 DEFUN ("require", Frequire, Srequire, 1, 2, 0,
2323 "If feature FEATURE is not loaded, load it from FILENAME.\n\
2324 If FEATURE is not a member of the list `features', then the feature\n\
2325 is not loaded; so load the file FILENAME.\n\
2326 If FILENAME is omitted, the printname of FEATURE is used as the file name.")
2327 (feature, file_name)
2328 Lisp_Object feature, file_name;
2329 {
2330 register Lisp_Object tem;
2331 CHECK_SYMBOL (feature, 0);
2332 tem = Fmemq (feature, Vfeatures);
2333 LOADHIST_ATTACH (Fcons (Qrequire, feature));
2334 if (NILP (tem))
2335 {
2336 int count = specpdl_ptr - specpdl;
2337
2338 /* Value saved here is to be restored into Vautoload_queue */
2339 record_unwind_protect (un_autoload, Vautoload_queue);
2340 Vautoload_queue = Qt;
2341
2342 Fload (NILP (file_name) ? Fsymbol_name (feature) : file_name,
2343 Qnil, Qt, Qnil, (NILP (file_name) ? Qt : Qnil));
2344
2345 tem = Fmemq (feature, Vfeatures);
2346 if (NILP (tem))
2347 error ("Required feature %s was not provided",
2348 XSYMBOL (feature)->name->data);
2349
2350 /* Once loading finishes, don't undo it. */
2351 Vautoload_queue = Qt;
2352 feature = unbind_to (count, feature);
2353 }
2354 return feature;
2355 }
2356 \f
2357 /* Primitives for work of the "widget" library.
2358 In an ideal world, this section would not have been necessary.
2359 However, lisp function calls being as slow as they are, it turns
2360 out that some functions in the widget library (wid-edit.el) are the
2361 bottleneck of Widget operation. Here is their translation to C,
2362 for the sole reason of efficiency. */
2363
2364 DEFUN ("widget-plist-member", Fwidget_plist_member, Swidget_plist_member, 2, 2, 0,
2365 "Return non-nil if PLIST has the property PROP.\n\
2366 PLIST is a property list, which is a list of the form\n\
2367 \(PROP1 VALUE1 PROP2 VALUE2 ...\). PROP is a symbol.\n\
2368 Unlike `plist-get', this allows you to distinguish between a missing\n\
2369 property and a property with the value nil.\n\
2370 The value is actually the tail of PLIST whose car is PROP.")
2371 (plist, prop)
2372 Lisp_Object plist, prop;
2373 {
2374 while (CONSP (plist) && !EQ (XCAR (plist), prop))
2375 {
2376 QUIT;
2377 plist = XCDR (plist);
2378 plist = CDR (plist);
2379 }
2380 return plist;
2381 }
2382
2383 DEFUN ("widget-put", Fwidget_put, Swidget_put, 3, 3, 0,
2384 "In WIDGET, set PROPERTY to VALUE.\n\
2385 The value can later be retrieved with `widget-get'.")
2386 (widget, property, value)
2387 Lisp_Object widget, property, value;
2388 {
2389 CHECK_CONS (widget, 1);
2390 XCDR (widget) = Fplist_put (XCDR (widget), property, value);
2391 }
2392
2393 DEFUN ("widget-get", Fwidget_get, Swidget_get, 2, 2, 0,
2394 "In WIDGET, get the value of PROPERTY.\n\
2395 The value could either be specified when the widget was created, or\n\
2396 later with `widget-put'.")
2397 (widget, property)
2398 Lisp_Object widget, property;
2399 {
2400 Lisp_Object tmp;
2401
2402 while (1)
2403 {
2404 if (NILP (widget))
2405 return Qnil;
2406 CHECK_CONS (widget, 1);
2407 tmp = Fwidget_plist_member (XCDR (widget), property);
2408 if (CONSP (tmp))
2409 {
2410 tmp = XCDR (tmp);
2411 return CAR (tmp);
2412 }
2413 tmp = XCAR (widget);
2414 if (NILP (tmp))
2415 return Qnil;
2416 widget = Fget (tmp, Qwidget_type);
2417 }
2418 }
2419
2420 DEFUN ("widget-apply", Fwidget_apply, Swidget_apply, 2, MANY, 0,
2421 "Apply the value of WIDGET's PROPERTY to the widget itself.\n\
2422 ARGS are passed as extra arguments to the function.")
2423 (nargs, args)
2424 int nargs;
2425 Lisp_Object *args;
2426 {
2427 /* This function can GC. */
2428 Lisp_Object newargs[3];
2429 struct gcpro gcpro1, gcpro2;
2430 Lisp_Object result;
2431
2432 newargs[0] = Fwidget_get (args[0], args[1]);
2433 newargs[1] = args[0];
2434 newargs[2] = Flist (nargs - 2, args + 2);
2435 GCPRO2 (newargs[0], newargs[2]);
2436 result = Fapply (3, newargs);
2437 UNGCPRO;
2438 return result;
2439 }
2440 \f
2441 syms_of_fns ()
2442 {
2443 Qstring_lessp = intern ("string-lessp");
2444 staticpro (&Qstring_lessp);
2445 Qprovide = intern ("provide");
2446 staticpro (&Qprovide);
2447 Qrequire = intern ("require");
2448 staticpro (&Qrequire);
2449 Qyes_or_no_p_history = intern ("yes-or-no-p-history");
2450 staticpro (&Qyes_or_no_p_history);
2451 Qcursor_in_echo_area = intern ("cursor-in-echo-area");
2452 staticpro (&Qcursor_in_echo_area);
2453 Qwidget_type = intern ("widget-type");
2454 staticpro (&Qwidget_type);
2455
2456 staticpro (&string_char_byte_cache_string);
2457 string_char_byte_cache_string = Qnil;
2458
2459 Fset (Qyes_or_no_p_history, Qnil);
2460
2461 DEFVAR_LISP ("features", &Vfeatures,
2462 "A list of symbols which are the features of the executing emacs.\n\
2463 Used by `featurep' and `require', and altered by `provide'.");
2464 Vfeatures = Qnil;
2465
2466 DEFVAR_BOOL ("use-dialog-box", &use_dialog_box,
2467 "*Non-nil means mouse commands use dialog boxes to ask questions.\n\
2468 This applies to y-or-n and yes-or-no questions asked by commands\n\
2469 invoked by mouse clicks and mouse menu items.");
2470 use_dialog_box = 1;
2471
2472 defsubr (&Sidentity);
2473 defsubr (&Srandom);
2474 defsubr (&Slength);
2475 defsubr (&Ssafe_length);
2476 defsubr (&Sstring_equal);
2477 defsubr (&Sstring_lessp);
2478 defsubr (&Sappend);
2479 defsubr (&Sconcat);
2480 defsubr (&Svconcat);
2481 defsubr (&Scopy_sequence);
2482 defsubr (&Sstring_make_multibyte);
2483 defsubr (&Sstring_make_unibyte);
2484 defsubr (&Scopy_alist);
2485 defsubr (&Ssubstring);
2486 defsubr (&Snthcdr);
2487 defsubr (&Snth);
2488 defsubr (&Selt);
2489 defsubr (&Smember);
2490 defsubr (&Smemq);
2491 defsubr (&Sassq);
2492 defsubr (&Sassoc);
2493 defsubr (&Srassq);
2494 defsubr (&Srassoc);
2495 defsubr (&Sdelq);
2496 defsubr (&Sdelete);
2497 defsubr (&Snreverse);
2498 defsubr (&Sreverse);
2499 defsubr (&Ssort);
2500 defsubr (&Splist_get);
2501 defsubr (&Sget);
2502 defsubr (&Splist_put);
2503 defsubr (&Sput);
2504 defsubr (&Sequal);
2505 defsubr (&Sfillarray);
2506 defsubr (&Schar_table_subtype);
2507 defsubr (&Schar_table_parent);
2508 defsubr (&Sset_char_table_parent);
2509 defsubr (&Schar_table_extra_slot);
2510 defsubr (&Sset_char_table_extra_slot);
2511 defsubr (&Schar_table_range);
2512 defsubr (&Sset_char_table_range);
2513 defsubr (&Sset_char_table_default);
2514 defsubr (&Smap_char_table);
2515 defsubr (&Snconc);
2516 defsubr (&Smapcar);
2517 defsubr (&Smapconcat);
2518 defsubr (&Sy_or_n_p);
2519 defsubr (&Syes_or_no_p);
2520 defsubr (&Sload_average);
2521 defsubr (&Sfeaturep);
2522 defsubr (&Srequire);
2523 defsubr (&Sprovide);
2524 defsubr (&Swidget_plist_member);
2525 defsubr (&Swidget_put);
2526 defsubr (&Swidget_get);
2527 defsubr (&Swidget_apply);
2528 }