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