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